ProRealCode - Trading & Coding with ProRealTime™
Hi Nicolas,
a request to convert this tradingsystem. I hope there’s interest in this!
Thank you.
The first 2 pics are probably from tradestation.
//@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')
You should also submit your request here https://www.prorealcode.com/free-code-conversion/
Thanks Francesco
I never submitted it that way.
there’s not enough interest which is too bad because it’s a good concept, although it has been around a long time.
I just want to point out that it’s interesting on a fast timeframe, maybe also a slower one and is a great base to experiment and build upon.
Created a code for long and that’a a new one, that works for now, on wallstreet, ftse, us russel2000, dax, sweden30, with the exact same parameters, with the correct spread, on the same timeframe and/or a timeframe close to it.
Most likely a lucky moment in time. It might however give someone new inspiration!
.
Did you managed to convert it? Looks interesting, but for now i’m out from low tf systems; i would like to make some tests on higher ones if you would like to share it, from the bottom of my skills 😀
yes, managed to convert the core and modified a bit. I will see how it goes. On higher timeframe it doesn’t seem to work good enough without curve-fitting.
I managed to convert it also (don’t know if good) and seems very promising, this is a first interaction with the DOW with any kind of optimization and with a random timeframe
But i think i also have your same problem, it only works on long 🙁
That’s a problem, short didn’t work at first glance. Nice to see you got something interesting to work with!
Muy buenas,
Desconozco porqué pero este indicador lo he copiado y pegado pero no me funciona. Me da errores de compilación.
Alguna persona me puede ayudar, por favor?
Very good, I do not know why but this indicator I have copied and pasted but it does not work for me. It gives me compilation errors. Can someone help me please?
Only post in the language of the forum that you are posting in. For example English only in the English speaking forums and French only in the French speaking forums.
Thank you 🙂
it’s not in ProRealTime language. It must be converted before you can use it with PRT.
(Sorry Roberto)
Good Morning,
I would need to know what application could convert me from Tradestation language to PRT please.
(or if there is information that can help me)
Thanks
I don’t know that language properly so couldn’t convert it, but I used the formula found on the internet to code an indicator (https://www.prorealcode.com/prorealtime-indicators/dual-thrust-strategy-indicator/) and this MTF strategy that simply enters a LONG position when the price crosses over the CAP and a SHORT position when it crosses under the FLOOR.
As suggested by the author, Stop & Reverse is the suggested way to close positions, but I added also fixed SL and TP (written and tested on DAX, 5min TF):
// Dual Thrust Strategy DAX mtf
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DEFPARAM CumulateOrders = FALSE
Timeframe(4h,UpdateOnClose)
//
cTime = OpenTime >= 050000 AND OpenTime <= 210000
cDay = OpenDayOfWeek >= 1 AND OpenDayOfWeek <= 5
TradeON = cTime AND cDay
//*********************************************************************************
// Dual Thrust setup
ONCE N = 4 //4 periods
ONCE K1 = 0.5 //0.5 K1 factor
ONCE K2 = K1 //K2 factor same as K1
// bands
HH = highest[N](high)
HC = highest[N](close)
LL = lowest[N](low)
LC = lowest[N](close)
// range
RNG = max(HH - LC,HC - LL)
// Cap & Floor
Cap = open + (RNG * K1)
Flr = open - (RNG * K2)
// ------------------------------------------------------------------------------
// LONG entry
IF close CROSSES OVER Cap AND Not LongOnMarket AND TradeON THEN
BUY 1 CONTRACT AT MARKET
ELSIF close CROSSES UNDER Flr AND Not ShortOnMarket AND TradeON THEN
SELLSHORT 1 CONTRACT AT MARKET
ENDIF
//
SET STOP pLOSS 100
SET TARGET pPROFIT 200
//
Timeframe(default)
//*********************************************************************************
// https://www.prorealcode.com/blog/trading/complete-trailing-stop-code-function/
// (righe 17- 56)
//
// trailing stop function by Nicolas (with the addition of DISTANCE and delayed start of N bars)
//
IF (BarIndex - TradeIndex) >= 0 THEN //0 bars dealy to start operating
trailingstart = 20 //20 trailing will start @trailinstart points profit
trailingstep = 5 //5 trailing step to move the "stoploss"
distance = 10 //10 pips distance from caurrent price (if required by the broker)
//reset the stoploss value
IF NOT ONMARKET THEN
newSL=0
ENDIF
//manage long positions
IF LONGONMARKET THEN
//first move (breakeven)
IF newSL=0 AND close-tradeprice(1)>=trailingstart*pipsize THEN
newSL = tradeprice(1)+trailingstep*pipsize
ENDIF
//next moves
IF newSL>0 AND close-newSL>=trailingstep*pipsize THEN
newSL = newSL+trailingstep*pipsize
ENDIF
ENDIF
//manage short positions
IF SHORTONMARKET THEN
//first move (breakeven)
IF newSL=0 AND tradeprice(1)-close>=trailingstart*pipsize THEN
newSL = tradeprice(1)-trailingstep*pipsize
ENDIF
//next moves
IF newSL>0 AND newSL-close>=trailingstep*pipsize THEN
newSL = newSL-trailingstep*pipsize
ENDIF
ENDIF
//stop order to exit the positions
IF newSL>0 THEN
IF LongOnMarket THEN
IF (close + distance) > newSL THEN
SELL AT newSL STOP
ELSIF (close - distance) < newSL THEN
SELL AT newSL LIMIT
ELSE
SELL AT Market
ENDIF
ELSIF ShortOnmarket THEN
IF (close + distance) < newSL THEN
EXITSHORT AT newSL STOP
ELSIF (close - distance) > newSL THEN
EXITSHORT AT newSL LIMIT
ELSE
EXITSHORT AT Market
ENDIF
ENDIF
ENDIF
ENDIF
//*********************************************************************************
Tested it with some modifications.
Would you mind posting your code, so that everyone knows where the results come from? Thank you 🙂
Would you mind posting your code, so that everyone knows where the results come from? Thank you 🙂
Of course. Pls find it attached.
convert request Dual Thrust Trading Algorithm
This topic contains 15 replies,
has 3 voices, and was last updated by
robertogozzi
4 years, 7 months ago.
| Forum: | ProOrder: Automated Strategies & Backtesting |
| Language: | English |
| Started: | 05/17/2020 |
| Status: | Active |
| Attachments: | 12 files |
The information collected on this form is stored in a computer file by ProRealCode to create and access your ProRealCode profile. This data is kept in a secure database for the duration of the member's membership. They will be kept as long as you use our services and will be automatically deleted after 3 years of inactivity. Your personal data is used to create your private profile on ProRealCode. This data is maintained by SAS ProRealCode, 407 rue Freycinet, 59151 Arleux, France. If you subscribe to our newsletters, your email address is provided to our service provider "MailChimp" located in the United States, with whom we have signed a confidentiality agreement. This company is also compliant with the EU/Swiss Privacy Shield, and the GDPR. For any request for correction or deletion concerning your data, you can directly contact the ProRealCode team by email at privacy@prorealcode.com If you would like to lodge a complaint regarding the use of your personal data, you can contact your data protection supervisory authority.