Challenge | Make this Strategy more Accurate without dropping P/L

Bingy

Member
Intro:
I'm curious to see what we can all achieve if we work together. Below I have laid the foundation of a winning strategy, that works for futures markets on the 15min timeframe. However, I'd like to make see if we can all come together and make it better then it already is. If you come up with something, share with the rest of us and pass the baton.

Rules:
• NO MULTI-TIMEFRAME(we don't want repainting)
• KEEP EXIT STRATEGY IS
• KEEP STOP LOSS AS IS
• FOCUS SOLEY ON ENTRY ACCURACY WITHOUT SACRIFICING P/L

This one has potential:

Code:
Code:
input averageLength = 14;
input paintbar = no;

def public = close[1] - open;
def pro =  close - open;

def avg_public = SimpleMovingAvg(public, averageLength);
def avg_pro = SimpleMovingAvg(pro, averageLength);
def res = avg_pro - avg_public;
def priceSMA = SimpleMovingAvg(close, averageLength);

def pu = avg_public; #red
def pr = avg_pro; #green

def condition1 = pu > pr;

##SHORTOLOGY/LONGOLOGY
input pd = 22;
input bbl = 20;
input mult = 2.0;
input lb = 50;
input ph = 0.85;
input pl = 1.01;
input hp = yes;
input sd = yes;
input distance_Thres = 0.29; #more conservative 0.15
input Longexit = 0.32;


def wvf = ((Highest(close, pd) - low) / Highest(close, pd)) * 100;

def sDev = mult * StDev(wvf, bbl);
def midLine = Average(wvf, bbl);
def lowerBand = midLine - sDev;
def upperBand = midLine + sDev;

def rangeHigh = (Highest(wvf, lb)) * ph;
def rangeLow = (Lowest(wvf, lb)) * pl;

# Calculate the distance between rangeHigh and rangeLow
def distance = rangeHigh - rangeLow;

# Check if the distance is less than or equal to the defined threshold
def isClose = if distance <= distance_Thres then 1 else 0;



############
############
############
# Check if the current close is higher than the previous bar
def closeHigher = close > close[1];

# Check if Signaling crosses above rangeHigh
def BullishDivergence = closeHigher and wvf crosses above rangeHigh;


############
############
############

#// ——————————— <inputs> {
input adxSmoothing = 14;#        'ADX Smoothing'
input diLength     = 14;#        'DI Length'
input Level_Range  = 20;#        'Level Range'
input Level_Trend  = 35;#        'Level Trend'
input alertOn      = yes;#      "Alert On/Off"
input barColor     = NO;#      "Bar Color On/Off"

def na = Double.NaN;
def last = isNaN(close);
def isconfirmed = !IsNaN(close);
#--- Color---
DefineGlobalColor("green"  , CreateColor(0, 100, 0));
DefineGlobalColor("lgreen" , CreateColor(56,142,60));
DefineGlobalColor("red"    , CreateColor(139,0,0));
DefineGlobalColor("lred"   , CreateColor(183,28,28));
DefineGlobalColor("orange" , CreateColor(255,152,0));

DefineGlobalColor("cgreen"  , CreateColor(0,61,0));
DefineGlobalColor("clgreen" , CreateColor(39,100,42));
DefineGlobalColor("cred"    , CreateColor(61,0,0));
DefineGlobalColor("clred"   , CreateColor(149,23,23));
DefineGlobalColor("corange" , CreateColor(118, 70, 0));

# function_declarations> {
script nz {
    input data  = close;
    def ret_val = if !isNaN(data) then data else 0;
    plot return = ret_val;
}
script fixnan {
    input source = close;
    def fix = if !IsNaN(source) then source else fix[1];
    plot result = fix;
}
#f_dirMov(_len) =>
script f_dirMov {
    input _len = 14;
    def _up        = (high - high[1]);
    def _down      = -(low - low[1]);
    def _plusDM    = if IsNaN(_up) then Double.NaN else if _up > _down and _up   > 0 then _up else 0;
    def _minusDM   = if IsNaN(_down) then Double.NaN else if _down > _up and _down > 0 then _down else 0;
    def tr = TrueRange(high, close, low);
    def _trueRange = WildersAverage(tr, _len);
    def _plus      = (100 * WildersAverage(_plusDM,  _len) / _trueRange);
    def _minus     = (100 * WildersAverage(_minusDM, _len) / _trueRange);
    def plus_      = if isNaN(_plus) then plus_[1] else _plus;
    def minus_     = if isNaN(_minus) then minus_[1] else _minus;
    plot plus = plus_;
    plot min  = minus_;
}
#f_sig(_diLen, _sigLen) =>
script f_sig {
    input _diLen = 14;
    input _sigLen = 14;
    def _plus = f_dirMov(_diLen).plus;
    def _minus = f_dirMov(_diLen).min;
    def _sum = _plus + _minus;
    def _sig = 100 * WildersAverage(AbsValue(_plus - _minus) / (if _sum == 0 then 1 else _sum), _sigLen);
    plot out = _sig;
}
#— <calculations> {
#//<set initial values>
def condition;#    = 0.0

def sig = f_sig(diLength, adxSmoothing);
def diPlus = f_dirMov(diLength).plus;
def diMinus = f_dirMov(diLength).min;

def hlRange     = sig     <= Level_Range;
def diUp        = diPlus  >= diMinus;
def diUpUp      = diPlus  >= Level_Trend;
def diDn        = diMinus >  diPlus;
def diDnDn      = diMinus >  Level_Trend;
def crossDi     = (diPlus>diMinus and diPlus[1]<=diMinus[1]) or (diPlus<diMinus and diPlus[1]>=diMinus[1]);
def sigUp       = sig > sig[1];
def sigDir      = if sig > sig[1] and diUp and !hlRange then 1 else
                  if sig > sig[1] and diDn and !hlRange then -1 else 0;
#//Rules
def entryLong    = !hlRange and diUp and sigUp and !diUp[1] or
                   !hlRange and diUp and sigUp and sig > Level_Range and hlRange[1];
def entryShort   = !hlRange and diDn and sigUp and !diDn[1] or
                   !hlRange and diDn and sigUp and sig > Level_Range and hlRange[1];
def entryLongStr = !hlRange and diUp and sigUp and diUpUp;
def entryShortSt = !hlRange and diDn and sigUp and diDnDn;
def exitLong     = crossDi and diUp[1] or hlRange and !hlRange[1];
def exitShort    = crossDi and diDn[1] or hlRange and !hlRange[1];
condition   = if condition[1] !=  1   and entryLongStr then 1 else
              if condition[1] != -1   and entryShortSt then -1 else
              if condition[1] != 0.5 and entryLong    then 0.5 else
              if condition[1] != -0.5 and entryShort  then -0.5 else
              if condition[1] !=  0   and exitLong    then 0  else
              if condition[1] !=  0   and exitShort   then 0  else nz(condition[1]);
def longE     = isconfirmed and
               condition[1] !=  0.5 and condition ==    0.5;
def shortE    = isconfirmed and
               condition[1] != -0.5 and condition ==   -0.5;
def longEStr  = isconfirmed and
               condition[1] !=  1   and condition ==    1;
def shortEStr = isconfirmed and
               condition[1] != -1   and condition ==   -1;
def longX     = isconfirmed and
             ((condition[1] ==  0.5 and condition ==    0) or
              (condition[1] ==  1   and condition ==    0));
def shortX    = isconfirmed and
             ((condition[1] == -0.5 and condition ==    0) or
              (condition[1] == -1   and condition ==    0));
#//<color>
def c_sig    = if hlRange then 0 else
               if sigUp   and diUp then 2 else
               if !sigUp  and diUp then 1 else
               if sigUp   and diDn then -2 else
               if !sigUp  and diDn then -1 else na;
def c_Adx    = if hlRange then 0 else
               if !hlRange and diUp and diUpUp  then 2 else
               if !hlRange and diUp and !diUpUp then 1 else
               if !hlRange and diDn and diDnDn then -2 else
               if !hlRange and diDn and !diDnDn then -1 else na;

#// ——————————— <plots> {
def adx = if last or isNaN(c_sig) then na else sig;


def p_diPlus     = if last then na else diPlus;


def p_diMinus    = if last then na else diMinus;




def LevelRange = if last then na else Level_Range;


def LevelTrend = if last then na else Level_Trend;


AssignPriceColor(if !barColor or isNaN(c_sig) then Color.CURRENT else
                 if c_sig==0 then GlobalColor("orange") else
                 if c_sig==2 then GlobalColor("green") else
                 if c_sig==1 then GlobalColor("lgreen") else
                 if c_sig==-2 then GlobalColor("red") else GlobalColor("lred"));

#// ——————————— <alerts> {
def Bullish = if alertOn and longE then Level_Trend + 10 else na;

def Bearish = if alertOn and shortE then Level_Trend + 10 else na;

def StrongBull = if alertOn and longEStr then Level_Trend + 10 else na;

def StrongBear = if alertOn and shortEStr then Level_Trend + 10 else na;

def EndTrend = if alertOn and (longX or shortX) then Level_Trend + 10 else na;




#-- END of Code

############
############
############



############
############
############
input price = close;
input length = 12;
input displace = 0;
input showBreakoutSignals = no;

def SMA = Average(price[-displace], length);

############
############
############


def RangeHigh2 = if hp then rangeHigh else Double.NaN;


def RangeLow2 = if hp then rangeLow else Double.NaN;


def Signaling = wvf;

def ADXconfirmed = C_Sig == 2 or C_Sig == 1;
;


Def SMAConfirmed = Close > SMA;



def Long = Signaling crosses below rangehigh

and SecondsFromTime(1045) >= 0 and
                    SecondsTillTime(1145) >= 0


and ADXconfirmed

and SMAConfirmed;



plot x = if Long then 1 else Double.NaN;
x.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
x.SetDefaultColor(Color.DARK_ORANGE);


#LONG ENTRY


AddOrder(OrderType.BUY_TO_OPEN, Long, open[-1], 4, tickcolor = Color.GREEN, arrowcolor = Color.GREEN);


#EXIT LONG POSITION


#1600 or 1245
def LongPositionExit = if Long then SecondsFromTime(1600) >= 0 else SecondsFromTime(1600) >= 0;





AddOrder(OrderType.SELL_TO_CLOSE, LongPositionExit, open[-1], 4, tickcolor = Color.RED, arrowcolor = Color.RED);



#STOP LOSS

######################
#STOP LOSS
######################

def Stop_loss = if
Long
then Lowest(low, 1) else Stop_loss[1];

# Check if the current close is below the stop loss level
def isStopTriggered = close < Stop_loss;

AddOrder(OrderType.SELL_TO_CLOSE, isStopTriggered, tickcolor = Color.DARK_ORANGE, arrowcolor = Color.DARK_ORANGE, name = "Stopped Out");
 
  • Love
Reactions: IPA
Solution
You are asking to make a moving average strategy "more accurate" without defining what you mean by accurate.

If you are asking whether it is possible to make scripts with moving average calculations less laggy and whipsaw-y;
it is not possible.

Think about pulling weights along the length of a chain that is dragging behind you.
Are those weights back along that chain going to be able to immediately alert you when the road starts to curve and that you should make a turn?

No, those weights don't start turning until well after you have passed that turn.

The general math is that moving averages lag 1/2 the length.
So it takes 7 bars after something has happened for your 14ma to register it.
And 10 bar after for your average using your...
You are asking to make a moving average strategy "more accurate" without defining what you mean by accurate.

If you are asking whether it is possible to make scripts with moving average calculations less laggy and whipsaw-y;
it is not possible.

Think about pulling weights along the length of a chain that is dragging behind you.
Are those weights back along that chain going to be able to immediately alert you when the road starts to curve and that you should make a turn?

No, those weights don't start turning until well after you have passed that turn.

The general math is that moving averages lag 1/2 the length.
So it takes 7 bars after something has happened for your 14ma to register it.
And 10 bar after for your average using your range's average length of 20.

Everything you wanted to know about moving average strategies:
https://usethinkscript.com/threads/lagging-indicator-accuracy-in-thinkorswim.15624/#post-126015

Lagging indicators are the most important part of any strategy, but not on your trading timeframe.
Range indicators such as yours are used on your higher timeframe to confirm trend / reversals
https://usethinkscript.com/threads/the-power-of-lagging-indicators-in-thinkorswim.17004/
Once confirmed, THEN use a non-lagging strategy to look for signals on your trading timeframe.
THEN confirm those signals are true on your lowest timeframe.

Read more about your three timeframes:
https://usethinkscript.com/threads/best-time-frame-for-trading-for-thinkorswim.12209/#post-104699
 
Last edited:
Solution

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
306 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top