Description
TACOS AND BEANS YO!
Categories & Tags
Comments (0)
0/2000
Loading comments…
Source code
function calculate(bars, ctx) {
// === Inputs ===
const showOpeningRange = ctx.input('Show Opening Range', true);
const orHighColor = ctx.input('Opening Range High Color', '#f23645');
const orLowColor = ctx.input('Opening Range Low Color', '#089981');
const orThickness = ctx.input('Opening Range Line Thickness', 2, { min: 1, max: 5, step: 1 });
const showVWAP = ctx.input('Show VWAP', true);
const vwapColor = ctx.input('VWAP Color', '#2962ff');
const vwapThickness = ctx.input('VWAP Line Thickness', 2, { min: 1, max: 5, step: 1 });
const showPivots = ctx.input('Show Pivot Points', true);
const pivotColor = ctx.input('Pivot Color', '#008080');
const r1Color = ctx.input('R1 Color', '#f23645');
const s1Color = ctx.input('S1 Color', '#089981');
const r2Color = ctx.input('R2 Color', '#f23645');
const s2Color = ctx.input('S2 Color', '#089981');
const pivotThickness = ctx.input('Pivot Line Thickness', 1, { min: 1, max: 5, step: 1 });
const showPrevDayLevels = ctx.input('Show Previous Day High/Low/Close', true);
const prevHighColor = ctx.input('Previous Day High Color', '#f23645');
const prevLowColor = ctx.input('Previous Day Low Color', '#089981');
const prevCloseColor = ctx.input('Previous Day Close Color', '#787b86');
const prevDayThickness = ctx.input('Previous Day Line Thickness', 1, { min: 1, max: 5, step: 1 });
const showSessionHL = ctx.input('Show Session High/Low', true);
const sessionHighColor = ctx.input('Session High Color', '#f23645');
const sessionLowColor = ctx.input('Session Low Color', '#089981');
const sessionThickness = ctx.input('Session Line Thickness', 1, { min: 1, max: 5, step: 1 });
// Session time inputs
const sessionStart = ctx.input('Session Start (ET)', 9, { min: 0, max: 23, step: 1 });
const sessionEnd = ctx.input('Session End (ET)', 16, { min: 0, max: 23, step: 1 });
const last = bars.length - 1;
if (last < 0) return;
// === Helper: check if bar is in NY session (ET) ===
function inSession(barIndex) {
const h = ctx.time.hourIn(barIndex, 'America/New_York');
if (sessionStart < sessionEnd) return h >= sessionStart && h < sessionEnd;
return h >= sessionStart || h < sessionEnd; // overnight wrap
}
// Track whether we just entered the session (for resetting session-level state)
let inSessionNow = false;
// === Opening Range (First 30 minutes after session start) ===
let openingRangeHigh = null;
let openingRangeLow = null;
let orStartBar = -1;
for (let i = 0; i <= last; i++) {
const inSess = inSession(i);
const prevInSess = i > 0 ? inSession(i - 1) : false;
// Detect session start
if (inSess && !prevInSess) {
// New session — figure out the opening range window (first 30 min)
// We'll find bars where minutes since session start are < 30
}
}
// Simpler approach: find the opening range by scanning session bars
// First, identify session start bar and count bars for 30 minutes
let sessionStartBar = -1;
let openingRangeIdx = -1;
let orHigh = -Infinity;
let orLow = Infinity;
for (let i = 0; i <= last; i++) {
const inSess = inSession(i);
const prevInSess = i > 0 ? inSession(i - 1) : false;
if (inSess && !prevInSess) {
// New session start
sessionStartBar = i;
openingRangeIdx = i;
orHigh = bars[i].high;
orLow = bars[i].low;
continue;
}
if (sessionStartBar >= 0 && inSess) {
// Count minutes since session start
const startHour = ctx.time.hourIn(sessionStartBar, 'America/New_York');
const startMin = ctx.time.minuteIn(sessionStartBar, 'America/New_York');
const currHour = ctx.time.hourIn(i, 'America/New_York');
const currMin = ctx.time.minuteIn(i, 'America/New_York');
const startTotalMin = startHour * 60 + startMin;
let currTotalMin = currHour * 60 + currMin;
// Handle overnight
if (currTotalMin < startTotalMin) currTotalMin += 1440;
const elapsed = currTotalMin - startTotalMin;
if (elapsed < 30) {
openingRangeIdx = i;
if (bars[i].high > orHigh) orHigh = bars[i].high;
if (bars[i].low < orLow) orLow = bars[i].low;
}
}
}
// === VWAP (session-anchored) ===
// Compute VWAP from session start to current bar
let vwapValues = new Array(bars.length).fill(null);
let sessionStartIdx = -1;
for (let i = 0; i <= last; i++) {
const inSess = inSession(i);
const prevInSess = i > 0 ? inSession(i - 1) : false;
if (inSess && !prevInSess) {
sessionStartIdx = i;
}
if (sessionStartIdx >= 0 && inSess) {
let pv = 0, v = 0;
for (let j = sessionStartIdx; j <= i; j++) {
const tp = (bars[j].high + bars[j].low + bars[j].close) / 3;
pv += tp * bars[j].volume;
v += bars[j].volume;
}
vwapValues[i] = v > 0 ? pv / v : null;
}
}
// === Pivot Points (from previous day's daily data) ===
// We need to find previous day's high/low/close
// Detect daily session boundaries
let prevDayHigh = null, prevDayLow = null, prevDayClose = null;
let currentDayHigh = -Infinity, currentDayLow = Infinity;
for (let i = 0; i <= last; i++) {
const isNewDay = ctx.time.isNewSession(i);
const h = bars[i].high;
const l = bars[i].low;
if (isNewDay && i > 0) {
// Previous day is completed — store its stats
prevDayHigh = currentDayHigh;
prevDayLow = currentDayLow;
prevDayClose = bars[i - 1].close;
// Reset for new day
currentDayHigh = h;
currentDayLow = l;
} else {
if (h > currentDayHigh) currentDayHigh = h;
if (l < currentDayLow) currentDayLow = l;
}
}
// Calculate pivot levels
let pivotLevel = null, r1 = null, s1 = null, r2 = null, s2 = null;
if (prevDayHigh != null && prevDayLow != null && prevDayClose != null) {
pivotLevel = (prevDayHigh + prevDayLow + prevDayClose) / 3;
r1 = pivotLevel + (pivotLevel - prevDayLow);
s1 = pivotLevel - (prevDayHigh - pivotLevel);
r2 = pivotLevel + (prevDayHigh - prevDayLow);
s2 = pivotLevel - (prevDayHigh - prevDayLow);
}
// === Session High/Low ===
let sessionHigh = -Infinity;
let sessionLow = Infinity;
let currentSessionStartBar = -1;
for (let i = 0; i <= last; i++) {
const inSess = inSession(i);
const prevInSess = i > 0 ? inSession(i - 1) : false;
if (inSess && !prevInSess) {
// New session
currentSessionStartBar = i;
sessionHigh = bars[i].high;
sessionLow = bars[i].low;
} else if (!inSess) {
// Outside session — reset
sessionHigh = -Infinity;
sessionLow = Infinity;
currentSessionStartBar = -1;
}
if (inSess) {
if (bars[i].high > sessionHigh) sessionHigh = bars[i].high;
if (bars[i].low < sessionLow) sessionLow = bars[i].low;
}
}
// === Draw everything ===
// 1. Opening Range
if (showOpeningRange && openingRangeIdx >= 0 && orHigh > -Infinity && orLow < Infinity) {
ctx.line(openingRangeIdx, orHigh, last, orHigh, {
color: orHighColor, lineWidth: orThickness, lineStyle: 'dashed'
});
ctx.line(openingRangeIdx, orLow, last, orLow, {
color: orLowColor, lineWidth: orThickness, lineStyle: 'dashed'
});
ctx.label(last, orHigh, 'OR High', { color: orHighColor, textColor: '#fff', size: 10, position: 'at', style: 'none' });
ctx.label(last, orLow, 'OR Low', { color: orLowColor, textColor: '#fff', size: 10, position: 'at', style: 'none' });
}
// 2. VWAP
if (showVWAP) {
ctx.plot(vwapValues, 'VWAP', { color: vwapColor, lineWidth: vwapThickness });
}
// 3. Pivot Points
if (showPivots && pivotLevel != null) {
ctx.hline(pivotLevel, { color: pivotColor, lineWidth: pivotThickness, lineStyle: 'dotted', label: 'Pivot' });
ctx.hline(r1, { color: r1Color, lineWidth: pivotThickness, lineStyle: 'dotted', label: 'R1' });
ctx.hline(s1, { color: s1Color, lineWidth: pivotThickness, lineStyle: 'dotted', label: 'S1' });
ctx.hline(r2, { color: r2Color, lineWidth: pivotThickness, lineStyle: 'dotted', label: 'R2' });
ctx.hline(s2, { color: s2Color, lineWidth: pivotThickness, lineStyle: 'dotted', label: 'S2' });
}
// 4. Previous Day High/Low/Close
if (showPrevDayLevels && prevDayHigh != null) {
ctx.hline(prevDayHigh, { color: prevHighColor, lineWidth: prevDayThickness, lineStyle: 'dashed', label: 'Prev High' });
ctx.hline(prevDayLow, { color: prevLowColor, lineWidth: prevDayThickness, lineStyle: 'dashed', label: 'Prev Low' });
ctx.hline(prevDayClose, { color: prevCloseColor, lineWidth: prevDayThickness, lineStyle: 'dashed', label: 'Prev Close' });
}
// 5. Session High/Low
if (showSessionHL && currentSessionStartBar >= 0 && sessionHigh > -Infinity && sessionLow < Infinity) {
ctx.line(currentSessionStartBar, sessionHigh, last, sessionHigh, {
color: sessionHighColor, lineWidth: sessionThickness, lineStyle: 'solid'
});
ctx.line(currentSessionStartBar, sessionLow, last, sessionLow, {
color: sessionLowColor, lineWidth: sessionThickness, lineStyle: 'solid'
});
ctx.label(last, sessionHigh, 'Session High', { color: sessionHighColor, textColor: '#fff', size: 10, position: 'at', style: 'none' });
ctx.label(last, sessionLow, 'Session Low', { color: sessionLowColor, textColor: '#fff', size: 10, position: 'at', style: 'none' });
}
}