Page 1 of 2
AUDUSD and the overlap continuation: does it still work after costs?
Posted: Tue Sep 22, 2026 1:38 pm
by LondonScalper
AUDUSD overlap continuation looked fine on charts until I forced a cost column.
Break-and-go ideas after Asia range were winning often enough to feel clever. After spread and a realistic slippage assumption, a chunk of those "wins" were noise. Continuation still exists — but only when the drive clears cost with room, and when I am not paying for the privilege of being early into a wide quote.
Cost-aware continuation checks
- Target beyond costs by a margin I respect, not tick-theatres
- Entry on shallow retest preferred over first spike through
- Skip if overlap spread is already elevated before the break
I would rather miss a clean runner than collect a set of costly almost-rights.
Has overlap continuation on AUDUSD survived your own cost review, or did you retire parts of it?
Continuation after costs also needs a clear invalidation; otherwise I am just hoping the overlap trend adopts me. Cost awareness without structure is only half a filter.
I would rather publish a smaller AUDUSD playbook that clears cost than a dramatic one that only wins before fees.
Re: AUDUSD and the overlap continuation: does it still work after costs?
Posted: Thu Sep 24, 2026 11:40 am
by FTtrader
LondonScalper wrote: Tue Sep 22, 2026 1:38 pm
AUDUSD overlap continuation looked fine on charts until I forced a cost column.
Break-and-go ideas after Asia range were winning often enough to feel clever. After spread and a realistic slippage assumption, a chunk of those "wins" were noise. Continuation still exists — but only when the drive clears cost with room, and when I am not paying for the privilege of being early into a wide quote.
Cost-aware continuation checks
- Target beyond costs by a margin I respect, not tick-theatres
- Entry on shallow retest preferred over first spike through
- Skip if overlap spread is already elevated before the break
I would rather miss a clean runner than collect a set of costly almost-rights.
Has overlap continuation on AUDUSD survived your own cost review, or did you retire parts of it?
Continuation after costs also needs a clear invalidation; otherwise I am just hoping the overlap trend adopts me. Cost awareness without structure is only half a filter.
I would rather publish a smaller AUDUSD playbook that clears cost than a dramatic one that only wins before fees.
Hello LondonScalper,
The realization that the cost column destroys a perfectly good chart pattern is a painful but necessary graduation in algorithmic trading. You have correctly identified the "tick-theatre"—where a strategy looks brilliant on a zero-fee backtest but bleeds out in the real world through a thousand tiny paper cuts of spread and slippage.
To answer your question directly: Yes, the raw AUDUSD overlap breakout had to be heavily heavily pruned, and large parts of it were entirely retired.
AUDUSD presents a unique structural problem for the Asia-to-London overlap. The Australian Dollar sees its primary volatility during the Asian session (driven by domestic and Chinese data). When London opens, AUDUSD often suffers a volatility drop while EUR and GBP pairs take center stage, leading to sluggish, grinding price action until the New York overlap.
Here is what was retired and what survived:
Retired: Stop-market orders placed just outside the Asia range. The spread widening right at the 08:00 Frankfurt / 09:00 London opens guarantees you pay maximum cost for the "privilege of being early."
Retired: Scalping the initial momentum. The London-open spikes on AUDUSD are frequently liquidity grabs (fake-outs) rather than true structural breaks.
Survived: The NY Overlap continuation. If the Asia range breaks during London, the true, cost-clearing continuation usually happens when New York opens and USD volume enters the market.
Survived: Limit orders on the structural retest. Forcing the market to come back to your price (the broken Asia high/low) is the only way to mathematically defend against the cost column.
Re: AUDUSD and the overlap continuation: does it still work after costs?
Posted: Thu Sep 24, 2026 11:40 am
by FTtrader
Here is a Pine Script (v5) built exactly to your specifications. It retires the "first spike" in favor of a limit-order retest, demands a strict target-to-cost margin, and sets a hard structural invalidation (the midpoint of the Asia range).
Code: Select all
//@version=5
strategy("Cost-Aware Asia Breakout (AUDUSD)", overlay=true, margin_long=100, margin_short=100)
// =========================================================================
// 1. INPUTS & FILTERS
// =========================================================================
grp1 = "Session Settings"
asiaSession = input.session("0000-0600", "Asia Session Range", group=grp1)
grp2 = "Cost & Risk Mechanics"
maxCostPips = input.float(1.5, "Expected Cost (Spread + Slippage in Pips)", step=0.1, group=grp2)
minCostMargin = input.float(3.0, "Target must be this many times the Cost", step=0.5, group=grp2)
riskReward = input.float(1.5, "Structural Risk/Reward Ratio", step=0.1, group=grp2)
maxSpreadCheck = input.float(2.0, "Skip if Live Spread Exceeds (Pips)", step=0.1, group=grp2)
// =========================================================================
// 2. PIP CALCULATION & SPREAD TRACKING
// =========================================================================
// Adjust for 5-digit forex brokers
pipSize = syminfo.mintick * (syminfo.type == "forex" ? 10 : 1)
liveSpread = (ask - bid) / pipSize
// =========================================================================
// 3. ASIA RANGE STATE MACHINE
// =========================================================================
var float asiaHigh = na
var float asiaLow = na
var float asiaMid = na
inSession = time(timeframe.period, asiaSession)
sessionStart = inSession and not inSession[1]
sessionEnd = not inSession and inSession[1]
if sessionStart
asiaHigh := high
asiaLow := low
if inSession
asiaHigh := math.max(asiaHigh, high)
asiaLow := math.min(asiaLow, low)
asiaMid := (asiaHigh + asiaLow) / 2
// Plotting the Range
plot(not inSession ? asiaHigh : na, color=color.new(color.green, 50), style=plot.style_linebr, title="Asia High")
plot(not inSession ? asiaLow : na, color=color.new(color.red, 50), style=plot.style_linebr, title="Asia Low")
plot(not inSession ? asiaMid : na, color=color.new(color.gray, 70), style=plot.style_linebr, title="Invalidation (Mid)")
// =========================================================================
// 4. BREAKOUT & RETEST LOGIC
// =========================================================================
// We only look for setups outside the Asia session
validTradingWindow = not inSession
// Identify the first clean close outside the range
breakoutLong = validTradingWindow and close > asiaHigh and close[1] <= asiaHigh
breakoutShort = validTradingWindow and close < asiaLow and close[1] >= asiaLow
// Calculate Structural Risk (Distance from Entry to Invalidation)
longRiskPips = (asiaHigh - asiaMid) / pipSize
shortRiskPips = (asiaMid - asiaLow) / pipSize
// Calculate targets based on Risk/Reward
longTargetPips = longRiskPips * riskReward
shortTargetPips = shortRiskPips * riskReward
// COST CHECK: Is the target significantly larger than our expected fees?
longCostCleared = longTargetPips >= (maxCostPips * minCostMargin)
shortCostCleared = shortTargetPips >= (maxCostPips * minCostMargin)
// LIVE SPREAD CHECK: Skip if spread is artificially elevated
spreadAcceptable = liveSpread <= maxSpreadCheck
// =========================================================================
// 5. EXECUTION (SHALLOW RETEST PREFERENCE)
// =========================================================================
// Instead of entering market on the breakout spike, we place a Limit Order
// exactly at the breakout level, valid only while the structure holds.
if breakoutLong and longCostCleared and spreadAcceptable
strategy.entry("Long Retest", strategy.long, limit=asiaHigh)
strategy.exit("Exit Long", "Long Retest", limit=asiaHigh + (longTargetPips * pipSize), stop=asiaMid)
if breakoutShort and shortCostCleared and spreadAcceptable
strategy.entry("Short Retest", strategy.short, limit=asiaLow)
strategy.exit("Exit Short", "Short Retest", limit=asiaLow - (shortTargetPips * pipSize), stop=asiaMid)
// Cancel orders if price hits invalidation BEFORE hitting our limit entry
if strategy.opentrades == 0 and validTradingWindow
if close < asiaMid
strategy.cancel("Long Retest")
if close > asiaMid
strategy.cancel("Short Retest")
// Cancel all pending orders when a new session starts to prevent stale setups
if sessionStart
strategy.cancel_all()
strategy.close_all("Session Reset")
Re: AUDUSD and the overlap continuation: does it still work after costs?
Posted: Thu Sep 24, 2026 11:41 am
by FTtrader
How this blueprint solves your cost problems
The Limit Order Mandate: By rejecting market orders on the breakoutLong condition and instead placing a limit=asiaHigh order, the script explicitly demands the "shallow retest." If the market spikes and runs without you, the order is eventually canceled. You keep your capital, and you miss the runner rather than paying for a sloppy entry.
Cost-Aware Margin Check: The minCostMargin variable ensures that the mathematical target is not just "technically profitable" but heavily outweighs your overhead. If your target is only generating twice your expected cost, the script refuses to place the order.
Hard Structural Invalidation: The asiaMid variable acts as a clear, structural stop loss. If the price breaks the range but then closes back below the midpoint of the Asia session, the breakout has failed mechanically. It cancels any pending limit orders instantly.
Pre-Break Spread Filter: The maxSpreadCheck blocks the script from placing orders if the broker's spread is highly elevated right at the moment the structural break occurs, preventing entries during thin liquidity pockets.
Re: AUDUSD and the overlap continuation: does it still work after costs?
Posted: Thu Sep 24, 2026 11:41 am
by FTtrader
Adding a Relative Volume (RVOL) filter forces the script to look for institutional footprints. When a breakout happens on low volume, it is usually a retail trap or a thin liquidity drift. When it happens on a volume spike (RVOL > 1.5x or 2.0x), it signals real participation, which is what actually pushes price to your target.
For Forex pairs like AUDUSD, brokers provide Tick Volume rather than centralized traded volume. Fortunately, tick volume is a highly reliable proxy for market activity and momentum—when the big players enter, quote frequency explodes.
Re: AUDUSD and the overlap continuation: does it still work after costs?
Posted: Thu Sep 24, 2026 11:41 am
by FTtrader
Here is the updated script. It adds an RVOL threshold that must be met on the exact candle that breaks the Asia range. If the breakout candle is weak, the limit order is never armed.
Code: Select all
//@version=5
strategy("Cost-Aware Asia Breakout + RVOL (AUDUSD)", overlay=true, margin_long=100, margin_short=100)
// =========================================================================
// 1. INPUTS & FILTERS
// =========================================================================
grp1 = "Session Settings"
asiaSession = input.session("0000-0600", "Asia Session Range", group=grp1)
grp2 = "Cost & Risk Mechanics"
maxCostPips = input.float(1.5, "Expected Cost (Spread + Slippage in Pips)", step=0.1, group=grp2)
minCostMargin = input.float(3.0, "Target must be this many times the Cost", step=0.5, group=grp2)
riskReward = input.float(1.5, "Structural Risk/Reward Ratio", step=0.1, group=grp2)
maxSpreadCheck = input.float(2.0, "Skip if Live Spread Exceeds (Pips)", step=0.1, group=grp2)
grp3 = "Volume & Momentum (RVOL)"
rvolLength = input.int(20, "RVOL Moving Average Length", minval=1, group=grp3)
rvolThreshold = input.float(1.5, "Minimum RVOL for Breakout", step=0.1, tooltip="1.5 means 150% of average volume", group=grp3)
// =========================================================================
// 2. PIP CALCULATION & SPREAD TRACKING
// =========================================================================
pipSize = syminfo.mintick * (syminfo.type == "forex" ? 10 : 1)
liveSpread = (ask - bid) / pipSize
// =========================================================================
// 3. ASIA RANGE STATE MACHINE
// =========================================================================
var float asiaHigh = na
var float asiaLow = na
var float asiaMid = na
inSession = time(timeframe.period, asiaSession)
sessionStart = inSession and not inSession[1]
sessionEnd = not inSession and inSession[1]
if sessionStart
asiaHigh := high
asiaLow := low
if inSession
asiaHigh := math.max(asiaHigh, high)
asiaLow := math.min(asiaLow, low)
asiaMid := (asiaHigh + asiaLow) / 2
plot(not inSession ? asiaHigh : na, color=color.new(color.green, 50), style=plot.style_linebr, title="Asia High")
plot(not inSession ? asiaLow : na, color=color.new(color.red, 50), style=plot.style_linebr, title="Asia Low")
plot(not inSession ? asiaMid : na, color=color.new(color.gray, 70), style=plot.style_linebr, title="Invalidation (Mid)")
// =========================================================================
// 4. RVOL CALCULATION
// =========================================================================
// Calculate the average volume and the current relative volume
avgVol = ta.sma(volume, rvolLength)
currentRVOL = volume / avgVol
// Optional: Plot a background color if a high volume bar occurs
bgcolor(currentRVOL >= rvolThreshold and not inSession ? color.new(color.blue, 90) : na, title="High RVOL Background")
// =========================================================================
// 5. BREAKOUT & RETEST LOGIC
// =========================================================================
validTradingWindow = not inSession
// Identify the first clean close outside the range WITH required volume
breakoutLong = validTradingWindow and close > asiaHigh and close[1] <= asiaHigh and currentRVOL >= rvolThreshold
breakoutShort = validTradingWindow and close < asiaLow and close[1] >= asiaLow and currentRVOL >= rvolThreshold
longRiskPips = (asiaHigh - asiaMid) / pipSize
shortRiskPips = (asiaMid - asiaLow) / pipSize
longTargetPips = longRiskPips * riskReward
shortTargetPips = shortRiskPips * riskReward
longCostCleared = longTargetPips >= (maxCostPips * minCostMargin)
shortCostCleared = shortTargetPips >= (maxCostPips * minCostMargin)
spreadAcceptable = liveSpread <= maxSpreadCheck
// =========================================================================
// 6. EXECUTION (SHALLOW RETEST PREFERENCE)
// =========================================================================
if breakoutLong and longCostCleared and spreadAcceptable
strategy.entry("Long Retest", strategy.long, limit=asiaHigh)
strategy.exit("Exit Long", "Long Retest", limit=asiaHigh + (longTargetPips * pipSize), stop=asiaMid)
if breakoutShort and shortCostCleared and spreadAcceptable
strategy.entry("Short Retest", strategy.short, limit=asiaLow)
strategy.exit("Exit Short", "Short Retest", limit=asiaLow - (shortTargetPips * pipSize), stop=asiaMid)
// Cancel orders if price hits invalidation BEFORE hitting our limit entry
if strategy.opentrades == 0 and validTradingWindow
if close < asiaMid
strategy.cancel("Long Retest")
if close > asiaMid
strategy.cancel("Short Retest")
// Session Reset
if sessionStart
strategy.cancel_all()
strategy.close_all("Session Reset")
Re: AUDUSD and the overlap continuation: does it still work after costs?
Posted: Thu Sep 24, 2026 11:42 am
by FTtrader
What changed mechanically
RVOL Calculation (Section 4): The script computes a Simple Moving Average (SMA) of the tick volume over your chosen lookback period (rvolLength, defaulting to 20). It divides the current bar's volume by this average.
The Filter: The breakoutLong and breakoutShort conditions now require currentRVOL >= rvolThreshold. If a candle crosses the Asia high but only has 1.2x the normal volume and your threshold is 1.5, the script considers it a fake-out and refuses to place the limit order.
Visual Debugging: A faint blue background highlight triggers on any high-RVOL candle outside the Asia session. This helps you visually scroll backward on the chart to calibrate what a "true" volume spike looks like for your specific timeframe.
Re: AUDUSD and the overlap continuation: does it still work after costs?
Posted: Thu Sep 24, 2026 11:43 am
by FTtrader
Moving this strategy to cTrader (which uses C# via the cAlgo API) requires a shift from Pine Script’s array-based logic to cTrader’s event-driven framework (OnTick and OnBar).
cTrader is fundamentally built for this kind of institutional execution. It handles strict limit order placement, tick volume reading, and live spread checking natively.
Here is the fully translated cBot in C#.
Re: AUDUSD and the overlap continuation: does it still work after costs?
Posted: Thu Sep 24, 2026 11:43 am
by FTtrader
cTrader cBot Code (C#)
Code: Select all
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class CostAwareAsiaBreakout : Robot
{
// =========================================================================
// 1. INPUTS & FILTERS
// =========================================================================
[Parameter("Trade Volume (Units)", Group = "Trade Settings", DefaultValue = 10000, MinValue = 1000)]
public double TradeVolume { get; set; }
[Parameter("Asia Start Hour (UTC)", Group = "Session Settings", DefaultValue = 0, MinValue = 0, MaxValue = 23)]
public int AsiaStartHour { get; set; }
[Parameter("Asia End Hour (UTC)", Group = "Session Settings", DefaultValue = 6, MinValue = 0, MaxValue = 23)]
public int AsiaEndHour { get; set; }
[Parameter("Expected Cost (Pips)", Group = "Cost & Risk Mechanics", DefaultValue = 1.5)]
public double MaxCostPips { get; set; }
[Parameter("Min Target/Cost Margin", Group = "Cost & Risk Mechanics", DefaultValue = 3.0)]
public double MinCostMargin { get; set; }
[Parameter("Risk/Reward Ratio", Group = "Cost & Risk Mechanics", DefaultValue = 1.5)]
public double RiskReward { get; set; }
[Parameter("Skip if Spread Exceeds (Pips)", Group = "Cost & Risk Mechanics", DefaultValue = 2.0)]
public double MaxSpreadCheck { get; set; }
[Parameter("RVOL Length", Group = "Volume & Momentum (RVOL)", DefaultValue = 20, MinValue = 1)]
public int RvolLength { get; set; }
[Parameter("Minimum RVOL", Group = "Volume & Momentum (RVOL)", DefaultValue = 1.5)]
public double RvolThreshold { get; set; }
// =========================================================================
// 2. STATE VARIABLES
// =========================================================================
private double _asiaHigh = double.NaN;
private double _asiaLow = double.NaN;
private double _asiaMid = double.NaN;
private bool _wasInSession = false;
private readonly string _label = "CostAwareBreakout";
// =========================================================================
// 3. EVENT: ON TICK (Manages Session State & Invalidations)
// =========================================================================
protected override void OnTick()
{
bool inSession = IsInSession(Server.Time);
bool sessionStart = inSession && !_wasInSession;
// Handle New Session Reset
if (sessionStart)
{
ResetSession();
}
// Track Highest High and Lowest Low during Asia Session
if (inSession)
{
double currentHigh = Bars.HighPrices.Last(0);
double currentLow = Bars.LowPrices.Last(0);
if (double.IsNaN(_asiaHigh) || currentHigh > _asiaHigh) _asiaHigh = currentHigh;
if (double.IsNaN(_asiaLow) || currentLow < _asiaLow) _asiaLow = currentLow;
_asiaMid = (_asiaHigh + _asiaLow) / 2;
// Draw levels visually on the chart
Chart.DrawHorizontalLine("AsiaHigh", _asiaHigh, Color.FromArgb(100, Color.Green));
Chart.DrawHorizontalLine("AsiaLow", _asiaLow, Color.FromArgb(100, Color.Red));
Chart.DrawHorizontalLine("AsiaMid", _asiaMid, Color.FromArgb(100, Color.Gray));
}
else
{
// Invalidation Check: If waiting on a limit order and price hits the mid-range
foreach (var order in PendingOrders.Where(o => o.Label == _label))
{
if (order.TradeType == TradeType.Buy && Symbol.Bid < _asiaMid)
{
CancelPendingOrder(order);
Print("Long limit order canceled: Price drifted back to structural invalidation (Asia Mid).");
}
else if (order.TradeType == TradeType.Sell && Symbol.Ask > _asiaMid)
{
CancelPendingOrder(order);
Print("Short limit order canceled: Price drifted back to structural invalidation (Asia Mid).");
}
}
}
_wasInSession = inSession;
}
// =========================================================================
// 4. EVENT: ON BAR (Manages Breakouts & Order Placement)
// =========================================================================
protected override void OnBar()
{
bool inSession = IsInSession(Server.Time);
// Only trade outside the session window, and only if range was established
if (inSession || double.IsNaN(_asiaHigh)) return;
// RVOL Calculation mapping Tick Volumes
double avgVol = 0;
for (int i = 1; i <= RvolLength; i++)
{
// Last(1) is the candle that just closed
avgVol += Bars.TickVolumes.Last(i);
}
avgVol /= RvolLength;
double currentVol = Bars.TickVolumes.Last(1);
double currentRvol = currentVol / avgVol;
double closeCurrent = Bars.ClosePrices.Last(1);
double closePrevious = Bars.ClosePrices.Last(2);
// Breakout Identifiers
bool breakoutLong = closeCurrent > _asiaHigh && closePrevious <= _asiaHigh && currentRvol >= RvolThreshold;
bool breakoutShort = closeCurrent < _asiaLow && closePrevious >= _asiaLow && currentRvol >= RvolThreshold;
if (breakoutLong || breakoutShort)
{
// Live Spread filter
double liveSpread = Symbol.Spread / Symbol.PipSize;
if (liveSpread > MaxSpreadCheck)
{
Print("Breakout ignored: Spread too high ({0} pips).", Math.Round(liveSpread, 1));
return;
}
if (breakoutLong)
{
double riskPips = (_asiaHigh - _asiaMid) / Symbol.PipSize;
double targetPips = riskPips * RiskReward;
if (targetPips >= MaxCostPips * MinCostMargin)
{
PlaceLimitOrder(TradeType.Buy, SymbolName, TradeVolume, _asiaHigh, _label, riskPips, targetPips);
Print("Long structural break validated. Limit placed at {0}, RVOL: {1}x", _asiaHigh, Math.Round(currentRvol, 2));
}
else
{
Print("Long breakout skipped: Required target ({0} pips) doesn't clear the cost margin requirement.", Math.Round(targetPips, 1));
}
}
if (breakoutShort)
{
double riskPips = (_asiaMid - _asiaLow) / Symbol.PipSize;
double targetPips = riskPips * RiskReward;
if (targetPips >= MaxCostPips * MinCostMargin)
{
PlaceLimitOrder(TradeType.Sell, SymbolName, TradeVolume, _asiaLow, _label, riskPips, targetPips);
Print("Short structural break validated. Limit placed at {0}, RVOL: {1}x", _asiaLow, Math.Round(currentRvol, 2));
}
else
{
Print("Short breakout skipped: Required target ({0} pips) doesn't clear the cost margin requirement.", Math.Round(targetPips, 1));
}
}
}
}
// =========================================================================
// 5. HELPER METHODS
// =========================================================================
private bool IsInSession(DateTime time)
{
if (AsiaStartHour < AsiaEndHour)
return time.Hour >= AsiaStartHour && time.Hour < AsiaEndHour;
else // Handles crossing midnight
return time.Hour >= AsiaStartHour || time.Hour < AsiaEndHour;
}
private void ResetSession()
{
_asiaHigh = double.NaN;
_asiaLow = double.NaN;
_asiaMid = double.NaN;
// Wipe out pending limit orders that never filled
foreach (var order in PendingOrders.Where(o => o.Label == _label))
{
CancelPendingOrder(order);
}
// Close any open trades to reset cleanly for the next session
foreach (var position in Positions.Where(p => p.Label == _label))
{
ClosePosition(position);
}
Chart.RemoveObject("AsiaHigh");
Chart.RemoveObject("AsiaLow");
Chart.RemoveObject("AsiaMid");
Print("New Asia Session started: Range cleared, stale orders and positions wiped.");
}
}
}
Re: AUDUSD and the overlap continuation: does it still work after costs?
Posted: Thu Sep 24, 2026 11:44 am
by FTtrader
Key Differences from Pine Script to Note:
Time Zones: By default, Pine Script relies on exchange time while this cBot explicitly uses UTC Time (TimeZones.UTC in the [Robot] header attribute). When you set 0 to 6 in the parameters, it means Midnight to 6 AM UTC. Adjust these parameters to match standard Asia timings in UTC rather than your local time.
OnBar vs OnTick execution: The breakout identification (price closing outside the range on high RVOL) triggers strictly inside OnBar() to eliminate intrabar repainting noise. However, the order invalidation (price breaking the mid-point of the range) is evaluated inside OnTick() to guarantee the limit order is canceled the exact second structure fails.
Volume Definition: While Pine Script required code handling to normalize pips, cTrader knows your symbol’s pip size automatically. Make sure to input your intended lot size properly in the parameters under Trade Volume (Units) (e.g., standard lot = 100000, micro lot = 1000).