- Square
- Dual Thrust Trading Algorithm (ps4)
Dual Thrust Trading Algorithm (ps4)
Author:
a624587332, Date: 2022-07-14 02:43:15
Tags:
//@version=4
study("Dual Thrust Trading Algorithm (ps4)", overlay=true)
// author: capissimo
// This is an PS4 update to the Dual Thrust trading algorithm developed by Michael Chalek.
// It has been commonly used in futures, forex and equity markets.
// The idea of Dual Thrust is similar to a typical breakout system,
// however dual thrust uses the historical price to construct update the look back period -
// theoretically making it more stable in any given period.
// see: https://www.quantconnect.com/tutorials/strategy-library/dual-thrust-trading-algorithm
//*** Inputs
p = input(20, "Lookback Window", minval=1)
mult = input(2.0, "Multiplier", minval=0.001, maxval=50)
rule = input("Original", "Trend Identification Rule", options=["Original","SMA3","EMA10","SMA5/SMA10"])
algo = input("Algo #1", "Algorithm used:", options=["Algo #1", "Algo #2"])
mlen = input(5, "Lookback Window M") // 4
nlen = input(14, "Lookback Window N") // 20
k = input(0.9, "Coeff", step=0.01) // .7, .9
disc = input(0.55, "Trending discount", step=0.01) // .6
use_bb = input(false, "Bollinger? (alt. Standard Error) Bands")
pbb = input(20, "Lookback Window", minval=1)
sdeg = input(3, "Smoothing Factor", minval=1)
multbb = input(2.0, "Bands Multiplier", minval=0.001, maxval=50)
repnt = input(true, "Repaint?")
//*** Main
O = security(syminfo.tickerid, tostring(timeframe.multiplier), repnt ? open : open[1], barmerge.gaps_off, barmerge.lookahead_on)
H = security(syminfo.tickerid, tostring(timeframe.multiplier), repnt ? high : high[1], barmerge.gaps_off, barmerge.lookahead_on)
L = security(syminfo.tickerid, tostring(timeframe.multiplier), repnt ? low : low[1], barmerge.gaps_off, barmerge.lookahead_on)
C = security(syminfo.tickerid, tostring(timeframe.multiplier), repnt ? close : close[1], barmerge.gaps_off, barmerge.lookahead_on)
// ==Bands==
//
// Standard Error of the Estimate (SEE) Bands are constructed around a linear regression curve and
// based on two standard errors above and below this regression line.
// The error bands measure the standard error of the estimate around the linear re-gression line.
// Therefore, as a price series follows the course of the regression line the bands will narrow,
// showing little error in the estimate. As the market gets noisy and random,
// the error will be greater resulting in wider bands.
beta(array,per) =>
val1 = sum(bar_index*array,per)-(per*sma(bar_index,per)*sma(array,per))
val2 = sum(pow(bar_index,2),per)-(per*pow(sma(bar_index,per),2))
calcB = val1/val2
alpha(array,per) =>
calcA = sma(array,per)-(beta(array,per)*sma(bar_index,per))
see(array,per,mult,dir,type) =>
lr = linreg(array,per,0)
val1 = (sum(pow(array,2),per))-((alpha(array,per)*sum(array,per)))-((beta(array,per)*sum(bar_index*array,per)))
val2 = per - 2
narrow = sqrt(val1/val2)
est = sum(pow(lr-array,2),per) / (per - 2 )
wide = sqrt(est)
d = dir ? 1 : -1
band = type ? narrow : wide
seb = lr + d * mult * band
// SEE Bands
UWB = plot(use_bb ? na: sma(see(close, pbb, 2.1, true, false), sdeg), color=color.blue, transp=90)
UNB = plot(use_bb ? na: sma(see(close, pbb, 2, true, true), sdeg), color=color.blue, transp=90)
plot(use_bb ? na: sma(linreg(close, pbb, 0), sdeg), color=color.orange, transp=0)
BNB = plot(use_bb ? na: sma(see(close, pbb, 2, false, true), sdeg), color=color.blue, transp=90)
BWB = plot(use_bb ? na: sma(see(close, pbb, 2.1, false, false), sdeg), color=color.blue, transp=90)
fill(UWB, BWB, title="WideSEE", color=color.blue)
fill(UNB, BNB, title="NarrowSEE", color=color.blue)
// Bollinger Bands
basis = sma(close, pbb)
dev = multbb * stdev(close, pbb)
upper = basis + dev
lower = basis - dev
plot(use_bb ? basis : na, color=color.orange, linewidth=2, transp=0)
fill(plot(use_bb ? upper : na, transp=65), plot(use_bb ? lower : na, transp=65), color=color.blue, transp=90)
// ==Dual Thrust Trading Algorithm==
// At the close of the day, calculate two values:
// the highest price - the closing price, and
// the closing price - the lowest price.
// Then take the two larger ones, multiply the k values. The results are called trig-ger values.
// On the second day, the opening price is recorded,
// and then immediately after the price exceeds (opening + trigger value),
// or the price is lower than the (opening - trigger value), the short selling immedi-ately.
// This is an inversion system without a single stop? i.e. the reverse signal is also the unwinding signal.
// K1 and K2 are the parameters.
// When K1 is greater than K2, it is much easier to trigger the long signal and vice versa.
// For demonstration, here we choose K1 = K2 = 0.5.
// In live trading, we can still use historical data to optimize those parameters or
// adjust the parameters according to the market trend.
// K1 should be small than k2 if you are bullish on the market and k1 should be much bigger if you are bearish on the market.
// Trend Identification - Bullish or Bearish
uptrend = false, dntrend = false
if rule=="Original"
rng = C - O
doji = rng == 0
uptrend := rng > 0 or doji and rng[1] > 0
dntrend := rng < 0 or doji and rng[1] < 0
else
sm = sma(C, 3) // #1
em = ema(C, 10) // #2
ma5 = sma(C, 5), ma10 = sma(C, 10) // #3
uptrend := rule=="SMA3" ? C > sm : rule=="EMA10" ? C > em : ma5 > ma10
dntrend := rule=="SMA3" ? C < sm : rule=="EMA10" ? C < em : ma5 < ma10
k1 = k, k2 = k
if uptrend // Assigned empirically. Should be optimized separately
k1 := k1 * disc //.2
k2 := k2 * (1 + disc)
if dntrend
k1 := k1 * (1 + disc)
k2 := k2 * disc //.2
dtta1_algo(k1, k2, len) =>
hh = highest(H, len)[1]
hc = highest(C, len)[1]
lc = lowest(C, len)[1]
ll = lowest(L, len)[1]
// The range is calculated based on the close, high and low over the most recent N-periods.
// A position is opened when the market moves a certain range from the opening price.
range = max(hh - lc, hc - ll)
[O + k1 * range, O - k2 * range]
dtta2_algo(k1, k2, ml, nl) =>
hh = 0.0, ll = 0.0, hc = 0.0, lc = 0.0
hh := highest(H, ml)[1]
hc := highest(C, ml)[1]
lc := lowest(C, ml)[1]
ll := lowest(L, ml)[1]
sellRange = (hh - lc) >= (hc - ll) ? hh - lc : hc - ll
hh := highest(H, nl)[1]
hc := highest(C, nl)[1]
lc := lowest(C, nl)[1]
ll := lowest(L, nl)[1]
buyRange = (hh - lc) >= (hc - ll) ? hh - lc : hc - ll
[O + k1 * buyRange, O - k2 * sellRange]
[bt1, st1] = dtta1_algo(k1, k2, mlen)
[bt2, st2] = dtta2_algo(k1, k2, mlen, nlen)
buyTrig = 0.0, sellTrig = 0.0
if algo == "Algo #1"
buyTrig := bt1, sellTrig := st1
else
buyTrig := bt2, sellTrig := st2
longCondition = C >= buyTrig
shortCondition = C <= sellTrig
state = 0
state := longCondition ? 1 : shortCondition ? -1 : nz(state[1])
long = change(state) and state[1]==-1
short = change(state) and state[1]==1
plotshape(uptrend and long ? low : na, location=location.belowbar, style=shape.labelup, color=color.green, size=size.tiny, text="B", textcolor=color.white, transp=0)
plotshape(dntrend and short ? high : na, location=location.abovebar, style=shape.labeldown, color=color.red, size=size.tiny, text="S", textcolor=color.white, transp=0)
alertcondition(long, title='Buy', message='go long')
alertcondition(short, title='Sell', message='go short')
More