0bps

Strategy vault / Trend following

Quantitative Trend Trading Strategy Using Polynomial Regression

This quantitative trading system uses polynomial regression analysis to identify potential trend reversals for entry signals. It aims to capitalize on momentum in a systematic, rules-based manner. How it Works The…

Author
ChaoZhang
Complexity
Intermediate · 198 lines
Parameters
14
Backtest bar
4h · intraday
Tested on
BTC/USDT · futures

This quantitative trading system uses polynomial regression analysis to identify potential trend reversals for entry signals. It aims to capitalize on momentum in a systematic, rules-based manner.

How it Works

The strategy fits polynomial regression lines to recent high and low prices. It tracks how many recent highs or lows exceed the regression forecast.

If a certain threshold of highs or lows breakout, a buy or sell signal is generated indicating an emerging trend. Stops and targets are set based on input percentages.

Positions are entered when the volatility angle exceeds a minimum to avoid choppy markets. Trades are managed based on the defined risk parameters.

Advantages and Drawbacks

By automating trend signals based on mathematical analysis, the strategy provides an objective approach to discretionary trading. Optimization can improve performance.

However, curve-fitting can lead to overoptimization. As with any technical system, performance depends heavily on market conditions. No strategy replaces prudent risk management.

Careful testing across different timeframes, asset classes and market environments is key to evaluate robustness. No strategy is foolproof, so managing risk is critical.

Overall, quantitative strategies offer a rules-based methodology for identifying potential trades. Blending mathematical and technical techniques can improve timing and risk calibration.

Parameters

NameDefaultWhat it controls
v_input_11.4Porcentaje Stop Loss
v_input_25.6Porcentaje Take Profit
v_input_326.8Angulo permitido
v_input_4true═══════════════ From ═══════════════
v_input_5trueMonth
v_input_6trueDay
v_input_72019Year
v_input_8true════════════════ To ════════════════
v_input_931Month
v_input_1012Day
v_input_119999Year
v_input_12true══════════════ Config ══════════════
v_input_134p
v_input_1426length

Source Pine Script

/*backtest
start: 2023-01-01 00:00:00
end: 2023-09-10 00:00:00
period: 4h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
//
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ //
//Ultima version underground09

// strategy(title = " underground09",
//          shorttitle = "Under09",
//          overlay = true,
//          precision = 8,
//          calc_on_order_fills = true,
//          calc_on_every_tick = true,
//          backtest_fill_limits_assumption = 0,
//          default_qty_type = strategy.fixed,
//          default_qty_value = 2,
//          initial_capital = 10000,
//          pyramiding=5,
//          currency = currency.USD,
//          linktoseries = true)

//
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ //
var sl = 0.0
var tp = 0.0
var acumaldor_vxp = 0.0
var acomuldor_vol = 0.0

//stop_loss = input(defval=0.2, title="Porcentaje Stop Loss", type=input.float, step=0.2)
stop_loss = input(defval=1.4, title="Porcentaje Stop Loss", type=input.float, step=0.2)
//take_profit = input(defval=4.4, title="Porcentaje Take Profit", type=input.float, step=0.2)
take_profit = input(defval=5.6, title="Porcentaje Take Profit", type=input.float, step=0.2)
//pintar_trade = input(defval=false, title="Pintar trade TP SL")
angulo_permitido = input(defval=26.8, title="Angulo permitido", type=input.float, step=0.2)

backTestSectionFrom = input(title = "═══════════════ From ═══════════════", defval = true, type = input.bool)

FromMonth         = input(defval = 1, title = "Month", minval = 1)
FromDay           = input(defval = 1, title = "Day", minval = 1)
FromYear          = input(defval = 2019, title = "Year", minval = 2014)

backTestSectionTo = input(title = "════════════════ To ════════════════", defval = true, type = input.bool)
ToMonth           = input(defval = 31, title = "Month", minval = 1)
ToDay             = input(defval = 12, title = "Day", minval = 1)
ToYear            = input(defval = 9999, title = "Year", minval = 2014)

Config            = input(title = "══════════════ Config ══════════════", defval = true, type = input.bool)
//p = input(6)
p = input(4)
//length = input(30)
length = input(26)
//
backTestPeriod() => (time > timestamp(FromYear, FromMonth, FromDay, 00, 00)) and (time < timestamp(ToYear, ToMonth, ToDay, 23, 59))
//
//
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ //

x1 = bar_index
x2 = sqrt(x1)
y = high
//
S11 = sum(x2,length) - sqrt(sum(x1,length)) / length  
S12 = sum(x1*x2,length) - (sum(x1,length) * sum(x2,length)) / length  
S22 = sum(sqrt(x2),length) - sqrt(sum(x2,length)) / length            
Sy1 = sum (y*x1,length) - (sum(y,length) * sum(x1,length)) / length   
Sy2 = sum (y*x2,length) - (sum(y,length) * sum(x2,length)) / length   
//
max1 = sma(x1,length) 
max2 = sma(x2,length)
may = sma(y,length)
b2 = ((Sy1 * S22) - (Sy2*S12))/(S22*S11 - sqrt(S12))
b3 = ((Sy2 * S11) - (Sy1 * S12))/(S22 * S11 - sqrt(S12))
b1 = may - b2*max1 - b3*max2
qr = b1 + b2*x1 + b3*x2
//
yl = low
//
Sy1l = sum(yl*x1,length) - (sum(yl,length) * sum(x1,length)) / length  
Sy2l = sum(yl*x2,length) - (sum(yl,length) * sum(x2,length)) / length  
//
mayl = sma(yl,length)
b2l = ((Sy1l * S22) - (Sy2l*S12))/(S22*S11 - sqrt(S12))
b3l = ((Sy2l * S11) - (Sy1l * S12))/(S22 * S11 - sqrt(S12))
b1l = mayl - b2l*max1 - b3l*max2
qrl = b1l + b2l*x1 + b3l*x2
//
period = round(p/2)+1
hh = qr[period]
ll = qrl[period]
countH = 0
countL = 0
buy=0
sell=0
//
for i = 1 to period-1
    if qr[i]<hh
        countH:=countH+1
    if qrl[i]>ll
        countL:=countL+1

for i = period+1 to p+1
    if qr[i]<hh
        countH:=countH+1
    if qrl[i]>ll
        countL:=countL+1

if countH==p
    pivotH = high[period]
    buy := 1
    
if countL==p
    pivotL = low[period]
    sell := 1
//
Angulo(_serie) =>
    atan( _serie - _serie[1] ) * 180 / acos(-1)
    
//calcular elvwap
vxp = volume*hlc3
//:= signo de acumulador
acumaldor_vxp := acumaldor_vxp + vxp
acomuldor_vol := acomuldor_vol + volume
vwap2 = acumaldor_vxp / acomuldor_vol

pendiente = Angulo(vwap2)

//  

plotshape(buy == 1 , text='⬆️', style=shape.arrowup, location=location.belowbar, color=#32CD32, textcolor=color.white, offset=0, transp=0,size=size.auto)
if buy == 1
    alert("Posible long",alert.freq_all )
    
plotshape(sell == 1 , text='⬇️', style=shape.arrowdown, location=location.abovebar, color=#FF0000, textcolor=color.white, offset=0, transp=0,size=size.auto)
if sell == 1
    alert("Posible short",alert.freq_all )
//

//if (backTestPeriod())
    //strategy.entry("long", true, 1, when = buy == 1)
    //    strategy.entry("short", false, 1, when = sell == 1) 

if buy == 1 and pendiente > angulo_permitido
//if buy == 1    
    cantidad = round(strategy.equity / close ) 
    strategy.entry("long", true, cantidad, comment = "Compra")
    sl := close * ( 1 - (stop_loss/100))
    tp := close * ( 1 + (take_profit/100))

if sell == 1 and pendiente > angulo_permitido
//if sell == 1 
    cantidad = round(strategy.equity / close ) 
    strategy.entry("short", false, cantidad, comment = "Venta")
    sl := close * ( 1 + (stop_loss/100))
    tp := close * ( 1 - (take_profit/100))
    
//Validaciones
comprado = strategy.position_size > 0 //true si es positivo
vendido = strategy.position_size < 0 //true si es negativo

if  comprado
    //Salir sl
    if  close >= tp
        //plotshape(close >= tp, style=shape.xcross)
        strategy.close("long", comment="TP")
        
    //Salir tp
    if  close <= sl
        strategy.close("long", comment="SL")
        
if  vendido
    //Salir sl
    if  close <= tp
        strategy.close("short", comment="TP")
    //Salir tp
    if  close >= sl
        strategy.close("short", comment="SL")

    
//sl tp
plot( sl , color =color.red, style=plot.style_cross)
plot( tp , color= color.green , style=plot.style_circles)

    
//color
//bgcolor (comprado ? color.green: na)
//bgcolor (vendido ? color.red: na)

//if pintar_trade 
    //bgcolor (close >= tp ? color.green : na, transp=80) 
    //bgcolor (close >= sl ? color.red : na, transp=80) 

Published by ChaoZhang on the FMZ strategy square · last modified 2023-09-11. Collected in the Quant Trading Vault. Unvalidated research: re-test with your own data and costs before trusting it.

Build this with AgenKit

A spec is not a trading system. Paste this into your coding agent and AgenKit runs a specialist team — architecture, test-first build, risk gates, review — with paper trading on by default.

in Claude Code, Cursor, Codex & 4 more
/agenkit build a production-grade trading bot with a backtest engine, risk controls and paper trading by default from strategies/Quantitative-Trend-Trading-Strategy-Using-Polynomial-Regression.md
  1. npx agenkit install engineering-kit in your project
  2. Paste the command into your agent and approve each phase
  3. Get tests, backtest, risk controls and a paper-trading switch

Understand it first

Before you run this, read the lesson behind the idea and how to backtest it honestly. Specs like this one are the survivors of an unknown number of trials; deflate their results accordingly.

Related specs

esc

Try , , or .

↑↓ move↵ open