Strategies
Freqtrade TrendFollowingStrategy — Frozen 5m EMA/OBV Source Port on LINK Futures
Outcome: Abandoned
FreqtradeFrozenLinkTrendFollowing
Outcome Summary
This strategy ported freqtrade's EMA20/OBV TrendFollowingStrategy unchanged to 5-minute LINK futures, long-only, with all parameters frozen. Its full-period backtest looked viable on cost: +6.25% over 513 trades and 0.335% per trade, which cleared the fee floor. Behind that, Sharpe was only 0.262 and it was 0.95 correlated with LINK buy-and-hold. Most profit came in 2020, and out-of-sample and holdout Sharpe were 0.02 and -0.34. After 2 iterations the analyst abandoned it on a hard positive-years gate failure (4 of 7), with no parameters left to tune and paper trading not recommended.
Hypothesis
This is a requested source replication, so historical momentum failures do not justify changing its signal rules or refusing the experiment. LINK avoids another BTC replication, although corpus_concentration is empty and its actual concentration is unknown. Literal inherited shorting behavior makes this long-only despite the futures file location; enabling shorts would change the original executable strategy. The source's fixed 5-minute timeframe rules out Hyperliquid for long-history validation. The requested replication takes precedence over portfolio quotas.
Implementation
Faithful port of freqtrade TrendFollowingStrategy on LINKUSDT.BINANCE 5m. Long entries come from the span-20 adjust=False EMA crossing combined with rising OBV. Short signals are calculated but never executed because the source inherits can_short=False. Exits are the exit_long signal; the ROI table {0:15%, 30:10%, 60:5%} as a resting reduce-only take-profit limit; and the -26.5% stoploss with its trailing stop (5% once profit passes the 10% offset) as a reduce-only intrabar stop that only moves up.
Iteration 2 fixes the QA finding: ROI exits no longer wait for a bar close. When the entry fills, a reduce-only GTC SELL LIMIT is placed at the fee-adjusted ROI price entry*(1+fee)*(1+roi)/(1-fee). At each bar close the strategy works out which ROI applies to the next bar and moves the limit at the 30- and 60-minute boundaries. Trade duration is measured at that bar's open, as Freqtrade does, so the platform's matching engine fills the limit inside the bar when price reaches the target. If the close is already above the newly applicable ROI, the strategy exits with a market order at that close, which is the next bar's open; Freqtrade exits at the candle open in the same case. When the position closes by any route, on_order_filled cancels whatever protection is left (the stop or the ROI limit). Signal logic, sizing, stoploss and trailing logic are unchanged.
Verification Results
No change required. If an exact match is wanted, document the bar-close ratchet in port_deviations.
Trailing-stop timing differs slightly from Freqtrade. At each bar close the level is ratcheted from the bar's high, and the strategy exits with a market order if the close is at or below the NEW level. Freqtrade's backtester resolves a trailing level updated inside the same candle with its own rules (it can apply the new level to that candle's low). For a close-based check the effect is small, and the resting reduce-only STOP_MARKET handles intrabar triggers at the previously ratcheted level.
Optionally resize the protective orders on a partial SELL fill.
If the ROI limit fills partially (event side SELL, position still open), the stop and the limit keep their original quantities. Both are reduce-only, so the position cannot flip. The simulated venue fills in full, so this cannot occur in a backtest.
None.
min_bars_required() = 1 overrides the base default of 20 (flagged by static analysis). This is deliberate and correct: the pandas ewm(adjust=False) EMA and TA-Lib OBV both seed on the first bar, and the frozen plan adds 200 warmup bars at window boundaries.
The sandbox covers 70 days with only 11 closed trades (10 wins near the 5% ROI tier, 1 loss of about -26.5% at the stop). A strategy that wins small and often but has a wide stop is sensitive to a few large losses, so the full history should be checked for stop-loss clustering in LINK selloffs. The sandbox report is not internally consistent: avg_holding_bars = 0.0 but avg_holding_period = 6d 3h; total_return 1.71 and max_drawdown 0.5186 do not fit a book that holds 3.8% exposure (they look like percent units). Positions are held for days on a perp, but funding_folded = false and funding_events_available = 0 in this window. The full backtest must include funding before the per-trade return (~4% of notional) is trusted.
Backtest Review
- Sharpe
- 0.26
- Total return
- 6.25%
- Max drawdown
- 8.25%
- Trades
- 513
- Win rate
- 84.8%
- Profit factor
- 1.08
513 closed long trades over 2,426 days provide a functioning, substantial sample. Inspected trades show equity-relative sizing and exits near the 5% ROI tier, consistent with the declared long-only implementation.
Net average trade return is 0.3352%, above the 0.15% futures review floor; profit factor is 1.0785 and total return is positive at 6.2525%. Proceed with frozen chronological validation rather than parameter tuning.
The full report resolves QA's missing-funding concern: funding is folded into PnL, 7,138 events are available, and inspected trades include funding debits.
QA's payoff concern remains relevant: average loss is $1,021 versus average win of $198. The 84.8% win rate leaves only modest positive expectancy.
Sharpe is 0.262, benchmark correlation is 0.951, and reported alpha and information ratio are negative. These warrant forward validation, not a pre-optimization rejection.
avg_holding_bars remains inconsistent with the reported multi-day holding duration; use dated trade records for duration assessment.
The requested outbox file could not be written because this session permits read-only filesystem access.
Analysis
Implementation works: 513 closed long-only trades, no shorts (matches inherited can_short=False), equity-relative sizing, zero end-position unrealized P&L, accounting reconciles.
Per-trade economics are above cost: avg_trade_return_pct 0.335% vs 0.20% futures economics floor; commissions are only 1.8% of gross, so fees are not the problem.
Max drawdown 8.25% is within the pre-registered 15% limit; all four evaluable pre-registered predictions were met (trades, return, DD, avg trade).
HARD gate failure (not waivable): positive in only 4 of 7 calendar years (57% < 60%). Promotion is impossible.
Edge is absent out of sample. Pooled outer OOS (15 chronological windows, ~3.9 years of hourly net MTM returns, 34,200 obs) has annual Sharpe 0.02 (t=0.04). The holdout Sharpe is -0.34 (t=-0.39). Neither is significant, but both are point estimates of zero or below, not thin positive evidence.
Profit is concentrated in the first year: 2020 contributes +4.90% of the +6.25% total (75% of profit). 2021-2026 together add about +1.35% over ~5.7 years. max_drawdown_duration_days = 1,947: no new equity high since early 2021.
No alpha versus LINK buy-and-hold: alpha -1.5%/yr, information ratio -0.74. Executed-signal IC is -0.036.
Picking-pennies payoff: win rate 0.85 with payoff ratio 0.19 (avg win $198 vs avg loss $1,021); PF 1.078; CVaR95 0.46% vs VaR95 0.29%; return skew -0.96, kurtosis 14.7.
Calmar 0.11 vs 0.5 floor; stress windows mostly negative (China ban 2021 -3.0%, LUNA -1.7%, FTX -1.6%, yen carry -1.0%).
soft
inconclusive
t >= 2
hard
t >= 2 (HAC/DSR)
advisory
Iteration History
Verification failed (Layer 4 — QA review) [class=hypothesis_mismatch]: - [critical] The source's minimal_roi declaration at original line 13 activates Freqtrade ROI exits when the intrabar price reaches the applicable target. Port lines 110–118 instead require the closing price to exceed that target, with no resting take-profit order. For example, after 60 minutes, a bar reaching 6% net profit but closing at 4% exits under the source's 5% ROI rule and remains open here. This changes the exit mechanism; the listed signal-close execution substitution does not disclose replacing intrabar ROI exits with close-only targets. Official semantics: [Freqtrade backtesting](https://www.freqtrade.io/en/stable/backtesting/#assumptions-made-by-backtesting). (line 118) — fix: Maintain a reduce-only resting take-profit at the fee-adjusted ROI price and update it at the 30- and 60-minute boundaries. Cancel competing protection when the position closes. Use platform matching rather than retrospectively filling from a completed bar's high.
Maintain a reduce-only resting take-profit at the fee-adjusted ROI price and update it at the 30- and 60-minute boundaries. Cancel competing protection when the position closes. Use platform matching rather than retrospectively filling from a completed bar's high.
The source's minimal_roi declaration at original line 13 activates Freqtrade ROI exits when the intrabar price reaches the applicable target. Port lines 110–118 instead require the closing price to exceed that target, with no resting take-profit order. For example, after 60 minutes, a bar reaching 6% net profit but closing at 4% exits under the source's 5% ROI rule and remains open here. This changes the exit mechanism; the listed signal-close execution substitution does not disclose replacing intrabar ROI exits with close-only targets. Official semantics: [Freqtrade backtesting](https://www.freqtrade.io/en/stable/backtesting/#assumptions-made-by-backtesting).
Outcome Summary
A high win rate with a large average trade return can hide a picking-up-pennies payoff (average win $198 vs average loss $1,021) and profit concentrated in one early year, so check yearly consistency and out-of-sample results before reading per-trade economics as an edge.
The backtest review sent it to optimization, but the post-optimization analyst abandoned it as premise_falsified because it failed a hard gate (positive in only 4 of 7 calendar years). The evidence also showed no edge: out-of-sample Sharpe of zero or below, 75% of profit from 2020, no new equity high for 1,947 days, and negative alpha against LINK buy-and-hold.
A frozen, faithful port of freqtrade's TrendFollowingStrategy on 5-minute LINKUSDT.BINANCE futures at 1x: enter long when close crosses above a span-20 EMA with rising OBV, exit through a 15/10/5% ROI ladder, a -26.5% stoploss and a trailing stop, with no shorts because the original inherits can_short=False.
Over 2,426 days and 513 long trades the backtest returned +6.25% with Sharpe 0.262, a 0.335% average trade return, an 84.8% win rate, profit factor 1.078 and 8.25% max drawdown; out of sample, the pooled walk-forward Sharpe was 0.02 (t=0.04) and the holdout Sharpe was -0.34.
Analysis
TrendFollowingStrategy
Analysis
TrendFollowingStrategy.py
Backtest and paper results are hypothetical. Trading involves risk of loss.