Three-Bar Strategy Guide

How ticks become bars, setups, trade levels, and entries

Back to dashboard

End-to-End Flow

1

Select ticker and timeframe

Only configured ticker/timeframe pairs build bars and run strategy checks.

2

Build completed bars

Live trade ticks update OHLC, volume, bar VWAP, and session VWAP.

3

Choose Bar 1 and Bar 2

The latest two completed, consecutive bars become the candidate pair.

4

Apply setup rules

Momentum, VWAP, inside-bar, range, volume, and midpoint checks must all pass.

5

Create trade levels

Entry trigger, stop, target, quantity, and risk are calculated before Bar 3 begins.

6

Watch Bar 3 ticks

Enter on trigger, reject on invalidation, or expire at the exact Bar 3 boundary.

1. Ticker and Timeframe Selection

Selected timeframe

  • Each ticker may have zero, one, or several selected timeframes.
  • The strategy independently builds and evaluates only the timeframes selected for that ticker.
  • A ticker with no selected timeframe does not build bars and does not run the three-bar strategy.

Strategy direction

  • Long-list tickers run only the long setup test.
  • Short-list tickers run only the short setup test.
  • A ticker in both lists can pass either direction, but only one active Bar 3 watch may own that ticker.

2. How Each Bar Is Built

  1. The tick timestamp is converted to New York time.
  2. The timestamp is floored to the timeframe boundary. The first tick in that bucket sets Open.
  3. Each later tick updates High, Low, Close, volume, price-volume, and session VWAP.
  4. The first tick in a later bucket finalizes the previous bar. Partial bars are never checked.
  5. Only completed bars are sent to the two-bar detector. An unfinished current bar is never evaluated.
Open = first tick price · High = maximum tick price · Low = minimum tick price · Close = latest tick price · Volume = sum of tick sizes
Bar VWAP = Σ(price × tick size) ÷ Σ(tick size)
Session VWAP = cumulative Σ(price × tick size) ÷ cumulative Σ(tick size), beginning when collection starts or is restored
Average bar volume = mean volume of completed bars for that ticker and timeframe, including the newly finalized bar
Market-open alignment: every timeframe is anchored to 09:30:00 New York time. For example, 2m produces 09:30–09:32 and 09:32–09:34; 4m produces 09:30–09:34 and 09:34–09:38.
Bar finalization: a bar closes when the first tick belonging to a later time bucket arrives.

3. Selecting Bar 1 and Bar 2

The detector reads the latest two completed bars for the same ticker and timeframe. They are accepted only when:

Bar 2 start time − Bar 1 start time = exactly one timeframe

4. Bar 1 and Bar 2 Rules

Long setup

  1. Bar 1 must be green: close > open.
  2. Bar 1 range must meet the timeframe expansion threshold.
  3. Bar 1 close must be at or above session VWAP.
  4. Bar 2 must remain inside Bar 1, with the configured tolerance.
  5. Bar 2 range must not exceed the configured fraction of Bar 1 range.
  6. Bar 2 volume must not exceed average bar volume × volume ratio.
  7. Bar 2 low must remain at or above the midpoint of Bar 1.

Short setup

  1. Bar 1 must be red: close < open.
  2. Bar 1 range must meet the timeframe expansion threshold.
  3. Bar 1 close must be at or below session VWAP.
  4. Bar 2 must remain inside Bar 1, with the configured tolerance.
  5. Bar 2 range must not exceed the configured fraction of Bar 1 range.
  6. Bar 2 volume must not exceed average bar volume × volume ratio.
  7. Bar 2 high must remain at or below the midpoint of Bar 1.
Bar 1 expansion passes when (high₁ − low₁) ≥ bar1_range × high₁
Inside limits: high₂ ≤ high₁ × (1 + inside_tol), and low₂ ≥ low₁ × (1 − inside_tol)
Bar 2 size: range₂ ≤ max_bar2_range_ratio × range₁
Volume pause: volume₂ ≤ avg_bar_volume₂ × volume_ratio
Bar 1 midpoint = low₁ + 0.5 × range₁
Implementation note: daily_avg_vwap is loaded into the check function but is not currently used as a pass/fail condition. The actual VWAP rule uses session VWAP.

Current Timeframe Parameters

Timeframe bar1_range inside_tol max_bar2_range_ratio volume_ratio
Loading parameters...

5. Trade-Level Decision

Long levels

Entry trigger = max(Bar 1 high, Bar 2 high)
Stop loss = Bar 2 low × 0.992
Target = entry trigger + risk multiple × risk per share

Short levels

Entry trigger = min(Bar 1 low, Bar 2 low)
Stop loss = Bar 2 high × 1.008
Target = entry trigger − risk multiple × risk per share
Risk per share = |entry trigger − stop loss|
Quantity = max(1, floor(current risk dollars ÷ risk per share))
Loading trade parameters...
Loading trade-level parameters...

6. Bar 3 Live-Tick Watch

  1. Signals are processed from shortest timeframe to longest.
  2. If the ticker already has an active Bar 3 watch, every later signal for that ticker is rejected. Signals are not queued.
  3. The watch ends at Bar 2 end time + one timeframe, which is the exact end of Bar 3.
  4. Long enters when a live tick is at or above the entry trigger.
  5. Short enters when a live tick is at or below the entry trigger.
  6. Long invalidates if a tick falls below Bar 2 low × (1 − invalidation tolerance).
  7. Short invalidates if a tick rises above Bar 2 high × (1 + invalidation tolerance).
  8. If no trigger occurs before the end time, the watch expires with no entry.
Loading Bar 3 parameters...
Bar 3 is not evaluated as a completed candle. It is a live-tick window whose duration equals the selected timeframe.

7. Order Finalization and Limits

  1. The triggering tick becomes the observed entry price.
  2. The internal entry trigger is rounded to cents.
  3. A long limit is placed above the trigger by the entry buffer; a short limit is placed below it.
  4. The long target is forced to at least 0.5% above the triggering tick; the short target is forced to at least 0.5% below it.
  5. The code builds a LIMIT OTOCO order with entry, target, and stop-loss legs.
  6. Execution is blocked or converted to dry run when execution switches or daily limits do not permit a new order.
Long entry limit = round(raw setup trigger × (1 + entry limit buffer), 2)
Short entry limit = round(raw setup trigger × (1 − entry limit buffer), 2)
Final long target = round(max(setup target, triggering tick × 1.005), 2)
Final short target = round(min(setup target, triggering tick × 0.995), 2)
Loading entry buffer parameter...

8. Skip Conditions and Daily Limits

  1. A setup is not created unless two completed consecutive bars exist.
  2. The same ticker/timeframe/Bar 2 combination is checked only once.
  3. Before starting Bar 3, the per-stock submitted-order count is checked. A ticker at its daily limit is skipped.
  4. A second Bar 3 signal for a ticker already being watched is rejected, even if it came from another timeframe.
  5. At execution, total daily trade count, EXECUTE_ORDERS, NEW_ENTRY, and the per-stock limit are checked again.
  6. The order count increments only after Webull returns HTTP 200 for submission.
Loading execution limits...

9. Post-Submission Stop Management

  1. This watch begins only after status SUBMITTED and only when a stop-loss client order ID exists.
  2. The code does not wait for a confirmed entry fill before registering this post-submission price watch.
  3. Risk is recalculated from the submitted entry limit to the original stop loss.
  4. Every later tick tracks the most favorable high for long trades or low for short trades.
  5. When price reaches the configured favorable R trigger, the stop-loss order is changed to the configured locked-in R level.

Long stop update

Update trigger = submitted entry limit + risk per share × STOP_UPDATE_R_TRIGGER
New stop = submitted entry limit + risk per share × STOP_UPDATE_R_LOCK

Short stop update

Update trigger = submitted entry limit − risk per share × STOP_UPDATE_R_TRIGGER
New stop = submitted entry limit − risk per share × STOP_UPDATE_R_LOCK
Loading stop-update parameters...