OrderVane

What a session boundary actually is

Every previous-session level — the high, the low, the value area, the point of control — is the output of a boundary someone chose. This is what I found when I tried to define that boundary in code, and why it was harder than it looks.

Why the boundary decides the numbers

A value area is volume-weighted arithmetic over a window. Move the window and every number moves with it.

On crude this is not a rounding difference. The electronic session runs around twenty-three hours; the US pit-equivalent window is roughly five and a half. The overnight portion carries real volume at prices the day session may never revisit. Compute value over the full electronic day and you get one pair of edges; compute it over regular hours and you get another. Both are correct arithmetic. They are answers to different questions.

So when someone quotes “yesterday’s VAH”, the number is only meaningful alongside the window that produced it. In practice that window is usually inherited from a platform default and never stated.

The session belongs to the chart, not the symbol

My first assumption in code was that the session definition is a property of the instrument — ask the symbol what its sessions are, and you have your boundary.

That was wrong, and the chart itself was the evidence. The shaded session bands a platform draws come from the session template selected on that chart, not from the instrument. Two charts of the same contract, open side by side, can shade different hours because they were configured differently.

Which means a tool that reads the symbol’s default can disagree with the shading the user is looking at, and the user is right. I had to read the chart’s container first and fall back to the symbol only when there was none.

What a platform calls the main session is not regular hours

The next assumption was that a session marked as the main or primary session is the regular-hours session. It reads that way in an API listing.

It is not. In the data I was working with, the session type enumeration distinguishes only pre-market, main, and post-market. An overnight-inclusive electronic session is typed as main, because from the venue’s point of view it is the main session — there is nothing pre or post about it.

So selecting “the main session” can hand you twenty-three hours while you believe you asked for five and a half. Nothing errors. The value area is computed correctly over the wrong window, and the only symptom is that your levels sit slightly off where you expected them.

The heuristic I ended up with, after the type field failed, was duration: among the main-typed sessions, the regular one is the shorter. That is a guess dressed as logic, and I would rather have had a field that said so.

Sometimes the regular session simply is not there

The result I did not expect: for the contract I was working on, the session container held exactly one session — a combined electronic-plus-regular definition. There was no regular-hours session to select. No amount of better selection logic was going to find one.

This is worth stating plainly because it is invisible from the chart. The shading looks authoritative. A drop-down offers session templates. But whether a separate regular-hours definition exists for your contract, on your data connection, is a fact about that connection, and it may simply be absent.

There was also a smaller trap underneath. The session open and close times came back as clock times that looked like exchange-local values but were UTC. Reading them as local produced a window shifted by hours — and a shifted window still produces perfectly plausible-looking levels. I only caught it because the resulting session did not line up with hours I already knew for crude.

What I did instead

Once it was clear the platform could not always answer the question, the honest options were to guess or to ask.

I made the window explicit and configurable, defaulting to the regular-hours times for crude rather than to whatever the container happened to return. That is a hardcoded assumption, which I dislike, but it is a stated one — visible in a setting, changeable, and wrong in a way the user can see and correct. The alternative was an inherited window that is wrong invisibly.

The general principle I took from it: when a platform cannot tell you which window it means, do not let the tool pretend it knows. Put the choice where the person can see it.

Honest limits

More research

Related docs: session levels · range profile