// Independent TradingView port of Distilled Desk's New York and London Time Ranges. // © DistilledTrades. Private research display; no orders or trade signals. //@version=6 indicator("Time Ranges",overlay=true,dynamic_requests=true,max_boxes_count=300,max_lines_count=500,max_labels_count=500) const string NY="America/New_York" const string LONDON="Europe/London" a0=input.bool(true,"08:50–09:10 → 10:55",group="New York windows") a1=input.bool(true,"10:50–11:10 → 12:10",group="New York windows") a2=input.bool(false,"Bell · 09:00–09:30 → 10:30",group="New York windows") a3=input.bool(false,"Pre-news · 07:30–08:30 → 12:30",group="New York windows") a4=input.bool(true,"Opening hour · 09:30–10:30 → 12:30",group="New York windows") a5=input.bool(false,"09:50–10:10 → 12:10",group="New York windows") a6=input.bool(false,"Pre-open · 07:00–08:00 → 10:00 UK",group="London windows") a7=input.bool(true,"Opening hour · 08:00–09:00 → 12:00 UK",group="London windows") showBands=input.bool(true,"Historical P30–P70 zones",group="Display",tooltip="Earlier complete same-symbol/feed sessions only, separately grouped by first edge and final outcome. 30+ observations for qualified bands; optional dashed previews use3–29. Conditional historical excursions, not targets or forecast probabilities.") previewBands=input.bool(true,"Show low-sample P-box previews",group="Display",tooltip="Exploratory preview with 3–29 earlier complete sessions in that exact side/outcome cohort. Dashed outline, LOW SAMPLE label and n. Does not relax the 30-session percentage threshold or mark a preview as qualified.") showLabels=input.bool(true,"Chart labels",group="Display") showPanel=input.bool(true,"Range status table",group="Display") keepDays=input.int(3,"Recent chart days",minval=1,maxval=5,group="Display") rangeInk=input.color(#4CAF50,"Range",group="Display") contInk=input.color(#29946e,"Continuation",group="Display") revInk=input.color(#ce6570,"Reversal",group="Display") header=input.color(#283238,"Table header",group="Display") rowsInk=input.color(#f0f0f0,"Table rows",group="Display") textInk=input.color(#20252b,"Table text",group="Display") where=input.string("Bottom right","Table position",options=["Top right","Top left","Bottom right","Bottom left"],group="Display") textSize=input.string(size.small,"Table text size",options=[size.tiny,size.small,size.normal],group="Display") weekdayFilter=input.string("All weekdays","Historical weekday filter",options=["All weekdays","Current range weekday"],group="Historical tendency") firstFilter=input.string("Auto · observed first edge","Historical first-break filter",options=["Auto · observed first edge","Both","High first","Low first"],group="Historical tendency",tooltip="Auto uses both sides before the first break, then the actual observed first edge. Fixed High/Low selections are labelled explicitly and are not today's detected direction.") cohortMax=input.int(250,"Earlier sessions retained per window",minval=60,maxval=500,group="History") sharedHistory=input.bool(true,"Use deeper shared minute history",group="History",tooltip="Loads actual native minutes through a background 1H context. The same symbol, range, first-side and outcome definitions are preserved. Only earlier complete sessions qualify. Each statistic uses the source with more samples; never adds overlapping source counts.") fineHistory=input.int(200000,"Native minute lookback",minval=5000,maxval=200000,step=5000,group="History",tooltip="Actual history depends on TradingView's plan, symbol and intrabar availability. Missing minutes are not filled. Low sample cohorts remain withheld.") int sec=int(timeframe.in_seconds(timeframe.main_period)) bool supported=chart.is_standard and sec>=30 and sec<=3600 // One exact closed minute is the atomic observation, including on a 30s chart. type Minute int t int e float o float h float l float c f_minute()=> Minute.new(time,time_close,open,high,low,close) type Sample int deadline int side int outcome float excursion float opposing type Range int id int start int finish int deadline string name bool enabled int last=na bool valid=true float hi=na float lo=na float postHi=na float postLo=na int side=0 int firstAt=na int reversalAt=na int state=0 // building 0, waiting 1, pending 2, reversal 3, continuation 4, ambiguous 5, unavailable 6, no break 7 bool archived=false array bands=na // high continuation P30/50/70, high reversal, low continuation, low reversal array counts=na array tendency=na // high C/R, low C/R; frozen at this range close string historySource="Chart" f_name(int i)=> i==0?"08:50–09:10":i==1?"10:50–11:10":i==2?"09:00–09:30":i==3?"07:30–08:30":i==4?"09:30–10:30":i==5?"09:50–10:10":i==6?"London 07:00–08:00":"London 08:00–09:00" f_zone(int i)=> i>=6?LONDON:NY f_zoneLabel(int i)=> i>=6?"UK":"NY" f_clocks(int t,int i)=> int startM=i==0?530:i==1?650:i==2?540:i==3?450:i==4?570:i==5?590:i==6?420:480 int endM=i==0?550:i==1?670:i==2?570:i==3?510:i==4?630:i==5?610:i==6?480:540 int stopM=i==0?655:i==1?730:i==2?630:i==3?750:i==4?750:i==5?730:i==6?600:720 string zone=f_zone(i) int y=year(t,zone),m=month(t,zone),d=dayofmonth(t,zone) [timestamp(zone,y,m,d,int(startM/60),startM%60),timestamp(zone,y,m,d,int(endM/60),endM%60),timestamp(zone,y,m,d,int(stopM/60),stopM%60)] // NumPy method="linear" parity: percentile position is (n-1)*q. f_linear(array values,float q)=> float at=(values.size()-1)*q int left=int(math.floor(at)) int right=int(math.ceil(at)) values.get(left)+(values.get(right)-values.get(left))*(at-left) f_quantiles(array history,Range r)=> r.bands:=array.new_float(12,na) r.counts:=array.new_int(4,0) r.tendency:=array.new_int(4,0) for sample in history if sample.deadline values=array.new_float() int side=cohort<2?1:-1 int outcome=cohort%2==0?4:3 for sample in history if sample.deadline=30 or previewBands and values.size()>=3 values.sort() r.bands.set(cohort*3,f_linear(values,.3)) r.bands.set(cohort*3+1,f_linear(values,.5)) r.bands.set(cohort*3+2,f_linear(values,.7)) 0 method step(Range r,Minute b,array history)=> if b.t>=r.start and b.t=math.max(b.o,b.c) and b.l<=math.min(b.o,b.c) if b.e-b.t!=60000 or (na(r.last)?b.t!=r.start:b.t!=r.last) or not prices r.valid:=false r.last:=b.e if b.tr.lo r.state:=r.valid?1:6 if r.valid f_quantiles(history,r) else if r.valid bool up=b.h>r.hi bool down=b.lcohortMax history.shift() r.archived:=true else if b.t>=r.deadline and not r.archived // Even one absent minute through the deadline invalidates the whole cohort. r.valid:=false r.state:=6 r.archived:=true 0 var h0=array.new() var h1=array.new() var h2=array.new() var h3=array.new() var h4=array.new() var h5=array.new() var h6=array.new() var h7=array.new() f_history(int i)=> i==0?h0:i==1?h1:i==2?h2:i==3?h3:i==4?h4:i==5?h5:i==6?h6:h7 var ranges=array.new() var int dateKey=na var int lastEnd=na var int gaps=0 f_dayKey(int t,string zone)=> year(t,zone)*10000+month(t,zone)*100+dayofmonth(t,zone) f_enabled(int i)=> i==0?a0:i==1?a1:i==2?a2:i==3?a3:i==4?a4:i==5?a5:i==6?a6:a7 // Each profile rolls on its own local date. London must not be reset at NY midnight. var profileDays=array.new_int(8,na) f_dispatch(Minute b,int key)=> for i=0 to 7 string zone=f_zone(i) int today=f_dayKey(b.t,zone) if na(profileDays.get(i)) or today!=profileDays.get(i) for r in ranges if r.id==i and not r.archived r.state:=6 r.valid:=false r.archived:=true if dayofweek(b.t,zone)>=dayofweek.monday and dayofweek(b.t,zone)<=dayofweek.friday [s,e,d]=f_clocks(b.t,i) ranges.push(Range.new(i,s,e,d,f_name(i),f_enabled(i))) profileDays.set(i,today) while ranges.size()>keepDays*8 ranges.shift() for r in ranges if not r.archived r.step(b,f_history(r.id)) f_dayKey(b.t,NY) // Native 1m requests on charts >=1m; native 30s pairs on the seconds chart. var int halfStart=na var Minute half=na if supported int cutoff=barstate.isrealtime?int(math.floor(timenow/60000)*60000):time_close array incoming=array.new() if sec>60 incoming:=request.security_lower_tf(syminfo.tickerid,"1",f_minute(),calc_bars_count=fineHistory) else if sec==60 incoming.push(f_minute()) else int minuteStart=time("1") if barstate.isconfirmed if time==minuteStart and time_close-time==30000 halfStart:=minuteStart half:=f_minute() else if not na(half) and halfStart==minuteStart and time==half.e and time_close-time==30000 and time_close==time_close("1") incoming.push(Minute.new(half.t,time_close,half.o,math.max(half.h,high),math.min(half.l,low),close)) half:=na for b in incoming if b.e<=cutoff and (na(lastEnd) or b.e>lastEnd) if not na(lastEnd) and b.t!=lastEnd gaps+=1 dateKey:=f_dispatch(b,dateKey) lastEnd:=b.e // Shared calibration runs in a deeper 1H context using complete native minute arrays. // It never returns or imports an event state into the chart's live detector. type HistoryBook array views array days array h0 array h1 array h2 array h3 array h4 array h5 array h6 array h7 int last=na int first=na int minutes=0 type HistoryBundle array views int last int first int minutes f_sharedBook()=> HistoryBook.new(array.new(),array.new_int(8,na),array.new(),array.new(),array.new(),array.new(),array.new(),array.new(),array.new(),array.new()) f_sharedSamples(HistoryBook book,int i)=> i==0?book.h0:i==1?book.h1:i==2?book.h2:i==3?book.h3:i==4?book.h4:i==5?book.h5:i==6?book.h6:book.h7 method ingestShared(HistoryBook book,Minute b)=> if na(book.last) or b.e>book.last if na(book.first) book.first:=b.t book.minutes+=1 for i=0 to 7 string zone=f_zone(i) int today=f_dayKey(b.t,zone) if na(book.days.get(i)) or today!=book.days.get(i) for view in book.views if view.id==i and not view.archived view.state:=6 view.valid:=false view.archived:=true if dayofweek(b.t,zone)>=dayofweek.monday and dayofweek(b.t,zone)<=dayofweek.friday [s,e,d]=f_clocks(b.t,i) Range view=Range.new(i,s,e,d,f_name(i),true) f_quantiles(f_sharedSamples(book,i),view) book.views.push(view) book.days.set(i,today) while book.views.size()>keepDays*8 book.views.shift() for view in book.views if not view.archived view.step(b,f_sharedSamples(book,view.id)) book.last:=b.e 0 f_sharedCalibration()=> var HistoryBook book=f_sharedBook() string historyTicker=ticker.modify(syminfo.tickerid,session=syminfo.session) array native=request.security_lower_tf(historyTicker,"1",f_minute(),currency=syminfo.currency,calc_bars_count=fineHistory) int cutoff=barstate.isrealtime?int(math.floor(timenow/60000)*60000):time_close for b in native if b.e<=cutoff book.ingestShared(b) // Returning collections on every requested bar would duplicate large buffers. HistoryBundle result=na if barstate.islast or barstate.islastconfirmedhistory result:=HistoryBundle.new(book.views,book.last,book.first,book.minutes) result // Direct minute context avoids reusing a short chart-minute dataset when available. f_sharedMinuteCalibration()=> var HistoryBook book=f_sharedBook() int cutoff=barstate.isrealtime?int(math.floor(timenow/60000)*60000):time_close if time_close<=cutoff book.ingestShared(f_minute()) HistoryBundle result=na if barstate.islast or barstate.islastconfirmedhistory result:=HistoryBundle.new(book.views,book.last,book.first,book.minutes) result f_applyShared(Range local,Range remote)=> bool used=false // Exact window/session key; frozen remote facts contain only deadlines before start. if local.id==remote.id and local.start==remote.start and not na(remote.tendency) if na(local.tendency) local.tendency:=array.new_int(4,0) if na(local.counts) local.counts:=array.new_int(4,0) if na(local.bands) local.bands:=array.new_float(12,na) if remote.tendency.sum()>local.tendency.sum() local.tendency:=remote.tendency.copy() used:=true for cohort=0 to 3 if remote.counts.get(cohort)>local.counts.get(cohort) local.counts.set(cohort,remote.counts.get(cohort)) for q=0 to 2 local.bands.set(cohort*3+q,remote.bands.get(cohort*3+q)) used:=true if used local.historySource:="Shared 1m" used HistoryBundle shared=na HistoryBundle sharedMinute=na if sharedHistory and supported shared:=request.security(syminfo.tickerid,"60",f_sharedCalibration(),gaps=barmerge.gaps_off,lookahead=barmerge.lookahead_off,calc_bars_count=int(math.ceil(fineHistory/60.0))+48) if sec<=60 sharedMinute:=request.security(ticker.modify(syminfo.tickerid,session=syminfo.session),"1",f_sharedMinuteCalibration(),gaps=barmerge.gaps_off,lookahead=barmerge.lookahead_off,calc_bars_count=fineHistory) if barstate.islast for source=0 to 1 HistoryBundle bundle=source==0?shared:sharedMinute if not na(bundle) and not na(bundle.views) for local in ranges for remote in bundle.views if local.id==remote.id and local.start==remote.start f_applyShared(local,remote) if not na(sharedMinute) and (na(shared) or sharedMinute.minutes>shared.minutes) shared:=sharedMinute // Render only after a new closed minute. State and calibration never use a forming minute. var boxes=array.new() var lines=array.new() var labels=array.new