Skip to content
All strategies

Strategies

Faithful port of CryptoRox 'Built-in Kelly ratio for dynamic position sizing' (TradingView, MPL-2.0): Keltner EMA20/ATR10x1.0 stop-entry stop-and-reverse with running-Kelly sizing, long-short, AVAXUSDT.OKX 4H

Outcome: Abandoned

KeltnerKellyStopReverse

Outcome Summary

KeltnerKellyStopReverse was a line-by-line port of a public TradingView Keltner breakout strategy with stop-and-reverse and Kelly sizing, assigned to AVAXUSDT.OKX 4H to add long-short OKX coverage to the corpus. The developer produced a partial FactoryStrategy implementation, but the coding stage timed out three times over 2 iterations and the run was abandoned ('coding_stuck_3_timeouts'). No backtest, optimization or analyst review ran, so the Keltner breakout family still has no measured verdict.

Hypothesis

Faithful line-by-line port of the TradingView Pine v4 strategy 'Built-in Kelly ratio for dynamic position sizing' by CryptoRox (https://www.tradingview.com/script/bFXf4IXh-Built-in-Kelly-ratio-for-dynamic-position-sizing/, MPL-2.0; all credit to the author). It is TradingView's default Keltner Channels strategy with a Kelly-fraction position size computed from the strategy's own closed-trade record. The script is a real, tradeable strategy, not a utility. The source names no instrument or timeframe. We assign……Show moreShow less

Faithful line-by-line port of the TradingView Pine v4 strategy 'Built-in Kelly ratio for dynamic position sizing' by CryptoRox (https://www.tradingview.com/script/bFXf4IXh-Built-in-Kelly-ratio-for-dynamic-position-sizing/, MPL-2.0; all credit to the author). It is TradingView's default Keltner Channels strategy with a Kelly-fraction position size computed from the strategy's own closed-trade record. The script is a real, tradeable strategy, not a utility. The source names no instrument or timeframe. We assign AVAXUSDT.OKX (OKX USDT perpetual swap) on 4-HOUR bars because OKX is 0.3% of the corpus against a >=5% target, the design is long-short (the corpus is 85% long-only), it is pure OHLCV so it needs no supplementary feed (L160), and 4H gives a multi-year history with a few hundred reversals. Bar type: AVAXUSDT.OKX-4-HOUR-LAST-EXTERNAL. DEFAULT PARAMETERS, exactly as written: length=20, mult=1.0, src=close, exp=true (EMA basis), BandsStyle='Average True Range', atrlength=10, useKelly=true, usetp=false, usesl=false, tp=10.0%, sl=1.0%, and a date range of 1900-2221 (always true, so omit it). Channel: ma = EMA(close,20) (SMA if exp=false); rangema = ATR(10) using Wilder RMA of the true range (the other styles are 'True Range' = RMA(TR,20) and 'Range' = RMA(high-low,20)); upper = ma + 1.0*rangema; lower = ma - 1.0*rangema. Signals, evaluated on bar close: crossUpper = close crosses over upper (prev close <= prev upper AND close > upper); crossLower = close crosses under lower. Stop prices: bprice latches high + one tick on each crossUpper bar and otherwise keeps its previous value; sprice latches low - one tick on each crossLower bar. crossBcond and crossScond latch true on the first crossUpper/crossLower and NEVER reset (a source quirk; keep it), so after the first cross cancelBcond is effectively (close < ma OR high >= bprice) and cancelScond is (close > ma OR low <= sprice). Order handling per bar, in the source's order: (1) if cancelBcond, cancel the pending Long stop order; (2) if crossUpper, place or replace the Long buy STOP-MARKET at bprice for qty; (3) if cancelScond, cancel the pending Short stop order; (4) if crossLower, place or replace the Short sell STOP-MARKET at sprice for qty. A pending stop stays working across bars until it fills, is cancelled, or is replaced. REVERSAL semantics (Pine strategy.entry with pyramiding=0): a Long fill while short closes the short and opens a long of qty, and vice versa. A same-direction entry while already in that direction is ignored. There are no other exits at the defaults (usetp/usesl=false), so after the first fill the book is always in a position and only flips side. KELLY SIZING (computed on each bar close from the strategy's own CLOSED trades, maintained as O(1) running counters, never rescanned): krp = wins/closed_trades; krw = gross_profit/wins; krl = gross_loss/losses (gross_loss as a positive magnitude); kr = krp - (1-krp)/(krw/krl). If any denominator is zero, kr is undefined, which Pine treats as na, so the 'kr > 0' test is false. qty = base_notional/close by default; if kr > 0, qty = equity*kr/close. Scaling to our capital: the source sets initial_capital=10000 with a 10000 fixed cash qty, i.e. the base notional equals 100% of initial capital, so base_notional = 100% of starting equity ($100,000, fixed, not compounding). Kelly notional = current equity * kr. Note the faithful quirk: when the record is losing (kr <= 0) or before trades exist, size is the full 100% base, and when the record is winning, size is only the Kelly fraction. Leverage 1.0; kr < 1 always, so notional never exceeds 1x equity. Optional exits, disabled by default, ported for completeness: TP = avg_entry_price*10% and SL = avg_entry_price*1% as bracket exits relative to the average entry. Fees: the source charges 0.1% per side; our backtest uses the OKX schedule of 0.02% maker / 0.05% taker. Stop-market fills are taker, so the round trip is about 0.10%, and each flip trade pays one side to close and one side to open. Any performance the TradingView page claims is unverified; our fee-inclusive backtest decides. Per-trade arithmetic: AVAX 4H ATR(10) is roughly 1.8-2.5% of price. A 1x-ATR Keltner break with stop-and-reverse is a trend-capture system with a win rate around 35-40%. Winners ride multi-day trends of 6-15%, losers are chop whipsaws of roughly 1-2 ATR, i.e. -2 to -4%. A plausible gross mean is +0.3 to +0.5% per trade against the 0.10% round trip, a 3-5x fee margin if the trend premium exists. Honest prior: this is a classic Keltner breakout family that has been tested before (an ETH Bybit 4H Keltner run died at sandbox timeout before producing metrics, so the family has no measured verdict yet). Lessons L150 and L167 warn that never-flat ports and public-script ports usually die. We propose it because the user asked for a faithful port, and we pre-register modest numbers.

The port follows the source line by line. The EMA is seeded at the first close (Pine ema), the RMA is seeded with the SMA (Pine rma), and tr(true) on the first bar is high-low. Crossover and crossunder match Pine exactly, bprice/sprice latch as in the source, and crossBcond/crossScond never reset. Pine evaluates orders on bar close, so order management runs in calculate_signal() in the source's order: cancel Long, place/replace Long, cancel Short, place/replace Short. The base template calls calculate_signal() on……Show moreShow less

The port follows the source line by line. The EMA is seeded at the first close (Pine ema), the RMA is seeded with the SMA (Pine rma), and tr(true) on the first bar is high-low. Crossover and crossunder match Pine exactly, bprice/sprice latch as in the source, and crossBcond/crossScond never reset. Pine evaluates orders on bar close, so order management runs in calculate_signal() in the source's order: cancel Long, place/replace Long, cancel Short, place/replace Short. The base template calls calculate_signal() on every primary bar even while stop orders rest. Its order-in-flight guard only blocks should_enter/should_exit, and both are deliberately inert here. Entries are venue-resting STOP_MARKET orders placed through _submit_stop_market. At the defaults the only exit is the reversal when the opposite stop fills. Pine computes the reversal quantity (qty + |position|) at fill time. The port reproduces this by re-syncing each pending stop's quantity via modify_order on every position open, change and close event. A pending stop on the side already held is cancelled. The Kelly counters (closed, wins, losses, gross profit, gross loss) are O(1) scalars updated in on_position_closed from realized PnL net of fees, matching Pine's trade profit, which is net of commission. A zero denominator maps to Pine's na, so the 'kr > 0' branch is skipped. Pine's strategy.equity includes open profit, so the Kelly notional uses account equity plus the position's unrealized PnL. The base notional is fixed at 100% of starting equity, matching the source's 10000 cash on 10000 initial capital. Adaptations: OKX fees (0.02% maker / 0.05% taker) replace the source's 0.1%, and the date-range filter is omitted because it is always true. No notional cap is applied, to stay faithful, so after a drawdown the fixed base notional can exceed 1x equity, as in the source. All state is kept in scalar attributes for restart parity; the SMA window deque only matters when exp=false. Honest prior: never-flat ports of public scripts usually fail the fee and OOS gates, and the backtest decides.

coding_stuck_3_timeouts

Implementation

Faithful port of CryptoRox's 'Built-in Kelly ratio for dynamic position sizing' (TradingView, MPL-2.0) on AVAXUSDT.OKX 4H bars. The Keltner channel is EMA(close,20) +/- 1.0 x ATR(10), with ATR as the Wilder RMA of the true range. When a close crosses over the upper band, the strategy places or replaces a resting BUY STOP at high + 1 tick. When a close crosses under the lower band, it places or replaces a SELL STOP at low - 1 tick. A pending stop is cancelled when price closes back through the basis; the source's latched crossBcond/crossScond quirk is kept. A stop fill reverses the book (order qty = qty + |position|), and a same-direction entry is ignored (pyramiding=0). Size is 100% of starting equity / close. When the running Kelly ratio of the strategy's own closed trades is > 0, size is current equity x Kelly / close instead. An optional TP of 10% and SL of 1% off the average entry is ported but disabled by default.

Iteration History

sandbox_timeout: Verification failed (Layer 3 — sandbox backtest): smoke test exceeded the 300s wall-clock limit on a ~20000-bar window (2400 days of AVAXUSDT.OKX-4-HOUR-LAST-EXTERNAL). This almost always means per-bar work that scales with history — e.g. rescanning the full funding/supplementary series, or rebuilding a list and calling min()/sorted() inside calculate_signal()/on_bar() on every bar. Precompute sorted timestamp arrays ONCE in __init__ and use bisect, or cache lookups keyed by timestamp, so per-bar cost is O(log n) not O(n).

Outcome Summary

Faithful stop-and-reverse ports with resting stop orders, reversal quantities and running Kelly counters are complex to code. Simplify the order-management layer, or split it into smaller pieces, so the developer can finish before the coding-stage timeout.

The run was abandoned in the coding stage with reason 'coding_stuck_3_timeouts' after 2 iterations. Verification, backtest, optimization, analyst and risk review were never reached.

A faithful port of CryptoRox's TradingView 'Built-in Kelly ratio' strategy: a long-short, always-in-market Keltner channel (EMA20 +/- 1.0x ATR10) system that enters and reverses on stop orders and sizes each position by a running Kelly fraction of its own closed trades, run on AVAXUSDT.OKX 4H bars.

No performance was measured: the backtest report is empty and no optimization report exists, so there are no return, Sharpe or trade-count figures.

Analysis

Built-in Kelly ratio for dynamic position sizing

Backtest and paper results are hypothetical. Trading involves risk of loss.