Worden Stochastic With Stops and Targets For ThinkOrSwim

mashume

Expert
VIP
Lifetime

WORDEN STOCHASTIC

An indicator and strategy by mashume
For trading with set stops and multiple targets


INTRODUCTION
I wanted to create an indicator that would pick lows and highs, but not designed to require me to be in a trade at all times after reading Trading in the Zone by Mark Douglas.

In the closing strategy portion of that book, he describes a system where you place a trade for three contracts, with stops and targets for each of the contracts set from the start of the trade. This is not an 'always in' trading strategy. If this doesn't make sense, read his book and then come back for this one. :)

Use it at your own risk and play with the settings. There are lots of options, and ways to tailor the indicator to your instrument of choice.

Note that the success percentages are not based on trades making targets, they are based on whether the trade is above (for long) the opening price a set number of bars after the trade is placed. It is beyond the coding presented here to check more fully than that. It is not a ToS Strategy, it is an indicator.

Happy Trading.

ordHFom.png


Code:
##############################################################
#
#   Worden Stochastic
#
#   A Strategy
#   with stops and targets on chart
#   and lots and lots of variations
#
#   (c) 2023 mashume (Seth Urion)
#   Released under GPLv3 to the UseThinkScript community
#
#   This software is released as is and with no warranty
#   of appropriateness or suitability for any task.
#
##############################################################

declare upper;

input upper = 77.5;
input lower = 22.5;
input kvo_length = 13;
input win_length = 15;
input k = 10;
input d = 10;
def rsi_value = RSI();
def rsi_value_u = RSI("over bought" = upper, "over sold" = lower).UpSignal;
input rsi_lookback = 3;
input Worden_length = 30;
input alerts = no;

script Worden {
    input length = 12;
    input k = 3;
    input d = 5;
    input OS = 20;
    input OB = 80;

    def rank = fold i = 0 to length with rankcounter = 0 do if close > GetValue(close, i) then rankcounter + 1 else rankcounter;

    def w = ( 100 / ( length – 1 ) ) * Rank;

    plot Worden = SimpleMovingAvg(w, k);
    plot signal = SimpleMovingAvg(Worden, d);
};

script klingerAlt {
    input MALength = 13;

    def DM = high - low;
    def Trend = if hlc3 > hlc3[1] then 1 else -1;
    def CM = DM + if Trend == Trend[1] then CM[1] else DM[1];

    def modVol = VOLUME / tick_count();
    def VForce = if CM != 0 then Trend * 100 * modVol * AbsValue(2 * DM / CM - 1) else VForce[1];
    plot KVOsc = ExpAverage(VForce, 34) - ExpAverage(VForce, 55);
    plot TriggerLine = Average(KVOsc, MALength);
};
input kvo_method = {default standard, alternate};
def kvosc;
switch (kvo_method) {
case standard:
    kvosc = KlingerOscillator(MALength = kvo_length).KVOsc;
case alternate:
    kvosc = klingerAlt(MALength = kvo_length).KVOsc;
}

def triggerLine = KlingerOscillator(MALength = kvo_length).TriggerLine;
def slowD = StochasticSlow("k period" = k, "d period" = d).SlowD;
def slowK = StochasticSlow("k period" = k, "d period" = d).SlowK;
input trade_loss = 50.0;

DefineGlobalColor(color = Color.RED, name = "pl_neg");
DefineGlobalColor(color = Color.WHITE, name = "pl_pos");
DefineGlobalColor(color = Color.YELLOW, name = "stopLoss");
input t1 = 1.0;
input t2 = 2.0;
input t3 = 4.0;

input Method = {default  "kvo + sto", "kvo + trigger dt", "kvo + trigger dt no zero", "kvo + sto + trigger dt", "kvo + sto no zero", "kvo + sto no cx", "kvo + rsi", "kvo Worden"};

def kosc_buy;
def kosc_sell;
def stoch_buy;
def stoch_sell;

switch (Method) {
case "kvo Worden":
    kosc_buy = if kvosc crosses above triggerLine
        and triggerLine < 0
        then 1 else 0;
    kosc_sell = if kvosc crosses below triggerLine
        and triggerLine > 0
        then 1 else 0;
    stoch_buy =
        if Worden(length = Worden_length).signal < lower
        # and Worden(length = Worden_length) < lower
        and Worden(length = Worden_length) > Worden(length = Worden_length).signal
        then 1 else 0;
    stoch_sell = 
        if Worden(length = Worden_length).signal > upper
        # and Worden() > upper
        and Worden(length = Worden_length) < Worden(length = Worden_length).signal
        then 1 else 0;
case "kvo + sto":
    kosc_buy = if kvosc crosses above triggerLine
        and triggerLine < 0
        then 1 else 0;
    kosc_sell = if kvosc crosses below triggerLine
        and triggerLine > 0
        then 1 else 0;
    stoch_buy = if slowD < lower and slowK < lower and (slowD < SlowK
        or (slowK crosses above lower and slowD < lower) )
        # or slowD crosses above lower
        then 1 else 0;
    stoch_sell = if slowD > upper and slowK > upper and (slowD > SlowK
        or (slowK crosses below upper and slowD > upper ))
        # or slowD crosses below upper
        then 1 else 0;
case "kvo + sto no cx":
    kosc_buy = if kvosc crosses above triggerLine
        and triggerLine < 0
        then 1 else 0;
    kosc_sell = if kvosc crosses below triggerLine
        and triggerLine > 0
        then 1 else 0;
    stoch_buy = if (slowD < lower) #  and slowK < lower)
        # or slowK crosses above lower
        # or slowD crosses above lower
        then 1 else 0;
    stoch_sell = if slowD > upper # and slowK > upper
        # or slowK crosses below upper
        # or slowD crosses below upper
        then 1 else 0;
case "kvo + sto no zero":
    kosc_buy = if kvosc crosses above triggerLine
    then 1 else 0;
    kosc_sell = if kvosc crosses below triggerLine
    then 1 else 0;
    stoch_buy = if slowD < lower or slowK < lower then 1 else 0;
    stoch_sell = if slowD > upper or slowK > upper then 1 else 0;
case  "kvo + sto + trigger dt":
    kosc_buy = if kvosc crosses above triggerLine
    and triggerLine - triggerLine[1] >= 0
    and triggerLine < 0
    then 1 else 0;

    kosc_sell = if kvosc crosses below triggerLine
    and triggerLine - triggerLine[1] <= 0
    and triggerLine > 0
    then 1 else 0;
    stoch_buy = if slowD < lower or slowK < lower then 1 else 0;
    stoch_sell = if slowD > upper or slowK > upper then 1 else 0;
case  "kvo + trigger dt":
    kosc_buy = if kvosc crosses above triggerLine
    and triggerLine - triggerLine[1] >= 0
    and triggerLine < 0
    then 1 else 0;

    kosc_sell = if kvosc crosses below triggerLine
    and triggerLine - triggerLine[1] <= 0
    and triggerLine > 0
    then 1 else 0;

    stoch_buy = 1;
    stoch_sell = 1;
case "kvo + trigger dt no zero":
    kosc_buy = if kvosc crosses above triggerLine
    and triggerLine - triggerLine[1] >= 0
    then 1 else 0;

    kosc_sell = if kvosc crosses below triggerLine
    and triggerLine - triggerLine[1] <= 0
    then 1 else 0;

    stoch_buy = 1;
    stoch_sell = 1;
case "kvo + rsi":
    kosc_buy = if kvosc crosses above triggerLine
    and kvosc <= 0
    then 1 else 0;

    kosc_sell = if kvosc crosses below triggerLine
    and kvosc >= 0
    then 1 else 0;

    stoch_buy = if rsi_value  < lower within rsi_lookback bars then 1 else 0;
    stoch_sell = if rsi_value > upper within rsi_lookback bars then 1 else 0;
}

plot long = if kosc_buy == 1 and stoch_buy == 1 then low else Double.NaN;

plot short = if kosc_sell == 1 and stoch_sell == 1 then high else Double.NaN;

def trade_length = if !IsNaN(long[1]) then 1 else trade_length[1] + 1;
def short_trade_length = if !IsNaN(short[1]) then 1 else short_trade_length[1] + 1;

def TradePrice = if !IsNaN(long[1]) then open else TradePrice[1];

# AddLabel(yes, "Last Trade Price = " + TradePrice, color.black);

def sl = if !IsNaN(long[1]) then open - (( trade_loss * TickSize() ) / TickValue()) else if trade_length <= 15 then sl[1] else Double.NaN;

plot Stop_loss = sl;

def tg = if !IsNaN(long[1]) then open + ((t1 * trade_loss * TickSize() ) / TickValue()) else if trade_length <= 30 then tg[1] else Double.NaN;

plot target = tg;

def tg2 = if !IsNaN(long[1]) then open + (( t2 * trade_loss * TickSize() ) / TickValue()) else if trade_length <= 45 then tg2[1] else Double.NaN;

plot target2 = tg2;

def tg3 = if !IsNaN(long[1]) then open + ((t3 * trade_loss * TickSize() ) / TickValue()) else if trade_length <= 60 then tg3[1] else Double.NaN;

plot target3 = tg3;

def sls = if !IsNaN(short[1]) then open + ((1 * trade_loss * TickSize() ) / TickValue()) else if short_trade_length <= 15 then sls[1] else Double.NaN;

plot short_Stop_loss = sls;

def tgs = if !IsNaN(short[1]) then open - ((t1 * trade_loss * TickSize() ) / TickValue()) else if short_trade_length <= 30 then tgs[1] else Double.NaN;

plot short_target = tgs;

def tgs2 = if !IsNaN(short[1]) then open - (( t2 * trade_loss * TickSize() ) / TickValue()) else if short_trade_length <= 45 then tgs2[1] else Double.NaN;

plot short_target2 = tgs2;

def tgs3 = if !IsNaN(short[1]) then open - ((t3 * trade_loss * TickSize() ) / TickValue()) else if short_trade_length <= 60 then tgs3[1] else Double.NaN;

plot short_target3 = tgs3;

# AddChartBubble("time condition" = !IsNaN(sl) and IsNaN(sl[1]), text = "SL " + (open - ((trade_loss * TickSize() ) / TickValue())), color = Color.YELLOW, up = no, "price location" = sl);

AddChartBubble("time condition" = (!IsNaN(sl) and IsNaN(sl[1]))
#  or sl[1] != sl
, text = "SL " + sl, color = GlobalColor("stopLoss"), up = no, "price location" = sl);

AddChartBubble("time condition" = (!IsNaN(sls) and IsNaN(sls[1]))
#  or sl[1] != sl
, text = "SL " + sls, color = GlobalColor("stopLoss"), up = yes, "price location" = sls);

stop_loss.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
stop_loss.SetLineWeight(2);
stop_loss.SetDefaultColor(Color.black);

target.SetPaintingStrategy(PaintingStrategy.DASHES);
target.SetLineWeight(1);
target.SetDefaultColor(Color.black);

target2.SetPaintingStrategy(PaintingStrategy.DASHES);
target2.SetLineWeight(1);
target2.SetDefaultColor(Color.black);

target3.SetPaintingStrategy(PaintingStrategy.DASHES);
target3.SetLineWeight(1);
target3.SetDefaultColor(Color.black);

short_stop_loss.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
short_stop_loss.SetLineWeight(2);
short_stop_loss.SetDefaultColor(Color.PLUM);

short_target.SetPaintingStrategy(PaintingStrategy.DASHES);
short_target.SetLineWeight(1);
short_target.SetDefaultColor(Color.PLUM);

short_target2.SetPaintingStrategy(PaintingStrategy.DASHES);
short_target2.SetLineWeight(1);
short_target2.SetDefaultColor(Color.PLUM);

short_target3.SetPaintingStrategy(PaintingStrategy.DASHES);
short_target3.SetLineWeight(1);
short_target3.SetDefaultColor(Color.PLUM);

short.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
short.SetLineWeight(4);
short.SetDefaultColor(Color.PLUM);

long.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
long.SetLineWeight(4);
long.SetDefaultColor(Color.Dark_Green);

Alert(condition = long and alerts == yes, text = "Enter Long", sound = Sound.Ring);

Alert(condition = short and alerts == yes, text = "Enter Long", sound = Sound.Ring);

AddLabel( (slowD <= lower and slowK <= lower and slowD < SlowK ), "Stochastic Ready LONG", Color.DARK_GREEN);

AddLabel( (slowD >= upper or slowK >= upper and slowD > SlowK ), "Stochastic Ready SHORT", Color.DARK_RED);

AddLabel( ((slowD < upper and slowK < upper) and  (slowD > lower and slowK > lower) ), "Stochastic Neutral", Color.GRAY);

AddLabel( (triggerLine <= 0 and kvosc < triggerLine), "Klinger Ready Long", Color.DARK_GREEN);

AddLabel( (triggerLine <= 0 and kvosc[1] < triggerLine[1]
 and kvosc > triggerLine), "Klinger Crossover Long!", Color.BLACK);

# AddLabel(  triggerLine - triggerLine[1] <= 0, "KVO T dt Negative", Color.DARK_RED);

# AddLabel(  triggerLine - triggerLine[1] > 0, "KVO T dt Positive", Color.DARK_GREEN);

def trades = if !IsNaN(long) then if IsNaN(trades[1]) then 1 else trades[1] + 1 else trades[1];

def wins = if !IsNaN(long[win_length]) and close[win_length - 1] < close then if IsNaN(wins[1]) then 1 else wins[1] + 1 else wins[1];

def win_rate = wins /  Max(trades, 1);

# addChartBubble(long, high + (8 * tickSize()), text = wins + " / " + trades, if win_rate > 0.666 then color.green else if win_rate < 0.333 then color.red else if win_rate > 0.5 then color.cyan else color.orange);

# AddChartBubble(long, high + (15 * TickSize()), text =  "L: " + Round(win_rate * 100, 0) + "%"
#  + " :: " + wins + " / " +  max((trades) - 1, 1)
# , if win_rate > 0.666 then Color.GREEN else if win_rate < 0.333 then Color.RED else if win_rate > 0.5 then Color.CYAN else Color.ORANGE);

AddLabel(yes, "LONG Rate: " + AsPercent(win_rate), if win_rate > 0.666 then Color.DARK_GREEN else if win_rate < 0.333 then Color.DARK_RED else if win_rate > 0.5 then Color.BLUE else Color.DARK_ORANGE);

def short_trades = if !IsNaN(short) then if IsNaN(short_trades[1]) then 1 else short_trades[1] + 1 else short_trades[1];

def short_wins = if !IsNaN(short[win_length]) and close[win_length - 1] > close then if IsNaN(short_wins[1]) then 1 else short_wins[1] + 1 else short_wins[1];

def short_win_rate = short_wins / Max(short_trades, 1);

AddLabel(yes, "SHORT Rate: " + AsPercent(short_win_rate), if short_win_rate > 0.666 then Color.DARK_GREEN else if short_win_rate < 0.333 then Color.DARK_RED else if short_win_rate > 0.5 then Color.BLUE else Color.DARK_ORANGE);

# addChartBubble(short, low - (8 * tickSize()), text = short_wins + " / " + short_trades, if short_win_rate > 0.666 then color.green else if short_win_rate < 0.333 then color.red else if short_win_rate > 0.5 then color.cyan else color.orange, up = No);

# AddChartBubble("time condition" = short, "price location" = high + (4 * TickSize()), text = "S: " + Round(short_win_rate * 100, 0) + "%", color = if short_win_rate > 0.666 then Color.GREEN else if short_win_rate < 0.333 then Color.RED else if short_win_rate > 0.5 then Color.CYAN else Color.ORANGE);

def profit_loss = if !IsNaN(long[win_length]) then close[-1] - open[win_length - 1] else Double.NaN;

def pl_dollars = (profit_loss / TickSize()) * TickValue();
def time_to_pl = if !IsNaN(long[win_length]) then ( GetTime() - GetTime()[win_length]) / 60000 else Double.NaN;

# AddChartBubble("time condition" = !IsNaN(profit_loss), text = "P/L  $" + AbsValue(pl_dollars) + "\n" + time_to_pl + " min", "price location" = low - 4 * TickSize(), up = no, color = if pl_dollars > 0 then GlobalColor("pl_pos") else GlobalColor("pl_neg"));

Alert(condition = alerts == yes and long[1], text = "Long Entry", "alert type" = Alert.BAR, sound = Sound.Bell);
Alert(condition = alerts == yes and short[1], text = "Short Entry", "alert type" = Alert.BAR, sound = Sound.Bell);

def in_trade = if !IsNaN(EntryPrice()) then 1 else 0;
Alert(condition = alerts == yes and high crosses above target and in_trade == 1, text = "Target 1", "alert type" = Alert.BAR, sound = Sound.Ding);

Alert(condition = alerts == yes and high crosses above target2 and in_trade == 1, text = "Target 2", "alert type" = Alert.BAR, sound = Sound.Ring);

# AddLabel(yes, "Tick Stop Loss: " + (( trade_loss * tickSize() )/ tickValue()), color.gray);
AddLabel(yes, " SL/T: " + AsDollars(trade_loss) + "   R/Rs :  " + t1 + ",  " + t2 + "    ", Color.DARK_GRAY);

# AddChartBubble("time condition" = long[win_length], "price location" = SL, text = "LOSS = " + asDollars( (open[win_length] - lowest(LOW, win_length)) / ticksize() * tickValue()), up = No, color = GlobalColor("pl_neg"));

plot stoSell = stoch_sell;


def long_trail_stop =
    if !IsNaN(long[1])
        then open - (( trade_loss * TickSize() ) / TickValue())
    else if trade_length <= 60    
        then
            if high - (( trade_loss * TickSize() ) / TickValue()) > long_trail_stop[1]
                then high - (( trade_loss * TickSize() ) / TickValue())
            else
                long_trail_stop[1]
    else
        Double.NaN;


def short_trail_stop = if !IsNaN(short[1]) then open + (( trade_loss * TickSize() ) / TickValue()) else if trade_length <= 60 then if low + (( trade_loss * TickSize() ) / TickValue()) < short_trail_stop[1] then low + (( trade_loss * TickSize() ) / TickValue()) else short_trail_stop[1] else Double.NaN;

plot short_trail = short_trail_stop;
plot long_trail = long_trail_stop;

# def long_open = if !IsNaN(long[1]) or !IsNaN(short[1]) then open else if trade_length <= 60 then long_open[1] else Double.NaN;
# plot trade_open = long_open;

# addCloud(trade_open, long_trail, color.red, color.green);
# addCloud(trade_open, short_trail, color.green, color.red);

P.S. There is a bunch of code that's commented out in there, and I think I got all the proprietary stuff removed. (I have another version that uses the BuyTheDip indicator in conjunction with those herein). I can't remember what all of the variations of this script were designed to do. Things like "no cx" means it doesn't need to cross (presumably the previous one needed a crossover to trigger). I think the default settings work fairly well and you can probably safely ignore everything but the stop loss value and the R:R settings.

This will be my last big post for a while. I think.

-mashume
 

WORDEN STOCHASTIC

An indicator and strategy by mashume
For trading with set stops and multiple targets


INTRODUCTION
I wanted to create an indicator that would pick lows and highs, but not designed to require me to be in a trade at all times after reading Trading in the Zone by Mark Douglas.

In the closing strategy portion of that book, he describes a system where you place a trade for three contracts, with stops and targets for each of the contracts set from the start of the trade. This is not an 'always in' trading strategy. If this doesn't make sense, read his book and then come back for this one. :)

Use it at your own risk and play with the settings. There are lots of options, and ways to tailor the indicator to your instrument of choice.

Note that the success percentages are not based on trades making targets, they are based on whether the trade is above (for long) the opening price a set number of bars after the trade is placed. It is beyond the coding presented here to check more fully than that. It is not a ToS Strategy, it is an indicator.

Happy Trading.

ordHFom.png


Code:
##############################################################
#
#   Worden Stochastic
#
#   A Strategy
#   with stops and targets on chart
#   and lots and lots of variations
#
#   (c) 2023 mashume (Seth Urion)
#   Released under GPLv3 to the UseThinkScript community
#
#   This software is released as is and with no warranty
#   of appropriateness or suitability for any task.
#
##############################################################

declare upper;

input upper = 77.5;
input lower = 22.5;
input kvo_length = 13;
input win_length = 15;
input k = 10;
input d = 10;
def rsi_value = RSI();
def rsi_value_u = RSI("over bought" = upper, "over sold" = lower).UpSignal;
input rsi_lookback = 3;
input Worden_length = 30;
input alerts = no;

script Worden {
    input length = 12;
    input k = 3;
    input d = 5;
    input OS = 20;
    input OB = 80;

    def rank = fold i = 0 to length with rankcounter = 0 do if close > GetValue(close, i) then rankcounter + 1 else rankcounter;

    def w = ( 100 / ( length – 1 ) ) * Rank;

    plot Worden = SimpleMovingAvg(w, k);
    plot signal = SimpleMovingAvg(Worden, d);
};

script klingerAlt {
    input MALength = 13;

    def DM = high - low;
    def Trend = if hlc3 > hlc3[1] then 1 else -1;
    def CM = DM + if Trend == Trend[1] then CM[1] else DM[1];

    def modVol = VOLUME / tick_count();
    def VForce = if CM != 0 then Trend * 100 * modVol * AbsValue(2 * DM / CM - 1) else VForce[1];
    plot KVOsc = ExpAverage(VForce, 34) - ExpAverage(VForce, 55);
    plot TriggerLine = Average(KVOsc, MALength);
};
input kvo_method = {default standard, alternate};
def kvosc;
switch (kvo_method) {
case standard:
    kvosc = KlingerOscillator(MALength = kvo_length).KVOsc;
case alternate:
    kvosc = klingerAlt(MALength = kvo_length).KVOsc;
}

def triggerLine = KlingerOscillator(MALength = kvo_length).TriggerLine;
def slowD = StochasticSlow("k period" = k, "d period" = d).SlowD;
def slowK = StochasticSlow("k period" = k, "d period" = d).SlowK;
input trade_loss = 50.0;

DefineGlobalColor(color = Color.RED, name = "pl_neg");
DefineGlobalColor(color = Color.WHITE, name = "pl_pos");
DefineGlobalColor(color = Color.YELLOW, name = "stopLoss");
input t1 = 1.0;
input t2 = 2.0;
input t3 = 4.0;

input Method = {default  "kvo + sto", "kvo + trigger dt", "kvo + trigger dt no zero", "kvo + sto + trigger dt", "kvo + sto no zero", "kvo + sto no cx", "kvo + rsi", "kvo Worden"};

def kosc_buy;
def kosc_sell;
def stoch_buy;
def stoch_sell;

switch (Method) {
case "kvo Worden":
    kosc_buy = if kvosc crosses above triggerLine
        and triggerLine < 0
        then 1 else 0;
    kosc_sell = if kvosc crosses below triggerLine
        and triggerLine > 0
        then 1 else 0;
    stoch_buy =
        if Worden(length = Worden_length).signal < lower
        # and Worden(length = Worden_length) < lower
        and Worden(length = Worden_length) > Worden(length = Worden_length).signal
        then 1 else 0;
    stoch_sell =
        if Worden(length = Worden_length).signal > upper
        # and Worden() > upper
        and Worden(length = Worden_length) < Worden(length = Worden_length).signal
        then 1 else 0;
case "kvo + sto":
    kosc_buy = if kvosc crosses above triggerLine
        and triggerLine < 0
        then 1 else 0;
    kosc_sell = if kvosc crosses below triggerLine
        and triggerLine > 0
        then 1 else 0;
    stoch_buy = if slowD < lower and slowK < lower and (slowD < SlowK
        or (slowK crosses above lower and slowD < lower) )
        # or slowD crosses above lower
        then 1 else 0;
    stoch_sell = if slowD > upper and slowK > upper and (slowD > SlowK
        or (slowK crosses below upper and slowD > upper ))
        # or slowD crosses below upper
        then 1 else 0;
case "kvo + sto no cx":
    kosc_buy = if kvosc crosses above triggerLine
        and triggerLine < 0
        then 1 else 0;
    kosc_sell = if kvosc crosses below triggerLine
        and triggerLine > 0
        then 1 else 0;
    stoch_buy = if (slowD < lower) #  and slowK < lower)
        # or slowK crosses above lower
        # or slowD crosses above lower
        then 1 else 0;
    stoch_sell = if slowD > upper # and slowK > upper
        # or slowK crosses below upper
        # or slowD crosses below upper
        then 1 else 0;
case "kvo + sto no zero":
    kosc_buy = if kvosc crosses above triggerLine
    then 1 else 0;
    kosc_sell = if kvosc crosses below triggerLine
    then 1 else 0;
    stoch_buy = if slowD < lower or slowK < lower then 1 else 0;
    stoch_sell = if slowD > upper or slowK > upper then 1 else 0;
case  "kvo + sto + trigger dt":
    kosc_buy = if kvosc crosses above triggerLine
    and triggerLine - triggerLine[1] >= 0
    and triggerLine < 0
    then 1 else 0;

    kosc_sell = if kvosc crosses below triggerLine
    and triggerLine - triggerLine[1] <= 0
    and triggerLine > 0
    then 1 else 0;
    stoch_buy = if slowD < lower or slowK < lower then 1 else 0;
    stoch_sell = if slowD > upper or slowK > upper then 1 else 0;
case  "kvo + trigger dt":
    kosc_buy = if kvosc crosses above triggerLine
    and triggerLine - triggerLine[1] >= 0
    and triggerLine < 0
    then 1 else 0;

    kosc_sell = if kvosc crosses below triggerLine
    and triggerLine - triggerLine[1] <= 0
    and triggerLine > 0
    then 1 else 0;

    stoch_buy = 1;
    stoch_sell = 1;
case "kvo + trigger dt no zero":
    kosc_buy = if kvosc crosses above triggerLine
    and triggerLine - triggerLine[1] >= 0
    then 1 else 0;

    kosc_sell = if kvosc crosses below triggerLine
    and triggerLine - triggerLine[1] <= 0
    then 1 else 0;

    stoch_buy = 1;
    stoch_sell = 1;
case "kvo + rsi":
    kosc_buy = if kvosc crosses above triggerLine
    and kvosc <= 0
    then 1 else 0;

    kosc_sell = if kvosc crosses below triggerLine
    and kvosc >= 0
    then 1 else 0;

    stoch_buy = if rsi_value  < lower within rsi_lookback bars then 1 else 0;
    stoch_sell = if rsi_value > upper within rsi_lookback bars then 1 else 0;
}

plot long = if kosc_buy == 1 and stoch_buy == 1 then low else Double.NaN;

plot short = if kosc_sell == 1 and stoch_sell == 1 then high else Double.NaN;

def trade_length = if !IsNaN(long[1]) then 1 else trade_length[1] + 1;
def short_trade_length = if !IsNaN(short[1]) then 1 else short_trade_length[1] + 1;

def TradePrice = if !IsNaN(long[1]) then open else TradePrice[1];

# AddLabel(yes, "Last Trade Price = " + TradePrice, color.black);

def sl = if !IsNaN(long[1]) then open - (( trade_loss * TickSize() ) / TickValue()) else if trade_length <= 15 then sl[1] else Double.NaN;

plot Stop_loss = sl;

def tg = if !IsNaN(long[1]) then open + ((t1 * trade_loss * TickSize() ) / TickValue()) else if trade_length <= 30 then tg[1] else Double.NaN;

plot target = tg;

def tg2 = if !IsNaN(long[1]) then open + (( t2 * trade_loss * TickSize() ) / TickValue()) else if trade_length <= 45 then tg2[1] else Double.NaN;

plot target2 = tg2;

def tg3 = if !IsNaN(long[1]) then open + ((t3 * trade_loss * TickSize() ) / TickValue()) else if trade_length <= 60 then tg3[1] else Double.NaN;

plot target3 = tg3;

def sls = if !IsNaN(short[1]) then open + ((1 * trade_loss * TickSize() ) / TickValue()) else if short_trade_length <= 15 then sls[1] else Double.NaN;

plot short_Stop_loss = sls;

def tgs = if !IsNaN(short[1]) then open - ((t1 * trade_loss * TickSize() ) / TickValue()) else if short_trade_length <= 30 then tgs[1] else Double.NaN;

plot short_target = tgs;

def tgs2 = if !IsNaN(short[1]) then open - (( t2 * trade_loss * TickSize() ) / TickValue()) else if short_trade_length <= 45 then tgs2[1] else Double.NaN;

plot short_target2 = tgs2;

def tgs3 = if !IsNaN(short[1]) then open - ((t3 * trade_loss * TickSize() ) / TickValue()) else if short_trade_length <= 60 then tgs3[1] else Double.NaN;

plot short_target3 = tgs3;

# AddChartBubble("time condition" = !IsNaN(sl) and IsNaN(sl[1]), text = "SL " + (open - ((trade_loss * TickSize() ) / TickValue())), color = Color.YELLOW, up = no, "price location" = sl);

AddChartBubble("time condition" = (!IsNaN(sl) and IsNaN(sl[1]))
#  or sl[1] != sl
, text = "SL " + sl, color = GlobalColor("stopLoss"), up = no, "price location" = sl);

AddChartBubble("time condition" = (!IsNaN(sls) and IsNaN(sls[1]))
#  or sl[1] != sl
, text = "SL " + sls, color = GlobalColor("stopLoss"), up = yes, "price location" = sls);

stop_loss.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
stop_loss.SetLineWeight(2);
stop_loss.SetDefaultColor(Color.black);

target.SetPaintingStrategy(PaintingStrategy.DASHES);
target.SetLineWeight(1);
target.SetDefaultColor(Color.black);

target2.SetPaintingStrategy(PaintingStrategy.DASHES);
target2.SetLineWeight(1);
target2.SetDefaultColor(Color.black);

target3.SetPaintingStrategy(PaintingStrategy.DASHES);
target3.SetLineWeight(1);
target3.SetDefaultColor(Color.black);

short_stop_loss.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
short_stop_loss.SetLineWeight(2);
short_stop_loss.SetDefaultColor(Color.PLUM);

short_target.SetPaintingStrategy(PaintingStrategy.DASHES);
short_target.SetLineWeight(1);
short_target.SetDefaultColor(Color.PLUM);

short_target2.SetPaintingStrategy(PaintingStrategy.DASHES);
short_target2.SetLineWeight(1);
short_target2.SetDefaultColor(Color.PLUM);

short_target3.SetPaintingStrategy(PaintingStrategy.DASHES);
short_target3.SetLineWeight(1);
short_target3.SetDefaultColor(Color.PLUM);

short.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
short.SetLineWeight(4);
short.SetDefaultColor(Color.PLUM);

long.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
long.SetLineWeight(4);
long.SetDefaultColor(Color.Dark_Green);

Alert(condition = long and alerts == yes, text = "Enter Long", sound = Sound.Ring);

Alert(condition = short and alerts == yes, text = "Enter Long", sound = Sound.Ring);

AddLabel( (slowD <= lower and slowK <= lower and slowD < SlowK ), "Stochastic Ready LONG", Color.DARK_GREEN);

AddLabel( (slowD >= upper or slowK >= upper and slowD > SlowK ), "Stochastic Ready SHORT", Color.DARK_RED);

AddLabel( ((slowD < upper and slowK < upper) and  (slowD > lower and slowK > lower) ), "Stochastic Neutral", Color.GRAY);

AddLabel( (triggerLine <= 0 and kvosc < triggerLine), "Klinger Ready Long", Color.DARK_GREEN);

AddLabel( (triggerLine <= 0 and kvosc[1] < triggerLine[1]
 and kvosc > triggerLine), "Klinger Crossover Long!", Color.BLACK);

# AddLabel(  triggerLine - triggerLine[1] <= 0, "KVO T dt Negative", Color.DARK_RED);

# AddLabel(  triggerLine - triggerLine[1] > 0, "KVO T dt Positive", Color.DARK_GREEN);

def trades = if !IsNaN(long) then if IsNaN(trades[1]) then 1 else trades[1] + 1 else trades[1];

def wins = if !IsNaN(long[win_length]) and close[win_length - 1] < close then if IsNaN(wins[1]) then 1 else wins[1] + 1 else wins[1];

def win_rate = wins /  Max(trades, 1);

# addChartBubble(long, high + (8 * tickSize()), text = wins + " / " + trades, if win_rate > 0.666 then color.green else if win_rate < 0.333 then color.red else if win_rate > 0.5 then color.cyan else color.orange);

# AddChartBubble(long, high + (15 * TickSize()), text =  "L: " + Round(win_rate * 100, 0) + "%"
#  + " :: " + wins + " / " +  max((trades) - 1, 1)
# , if win_rate > 0.666 then Color.GREEN else if win_rate < 0.333 then Color.RED else if win_rate > 0.5 then Color.CYAN else Color.ORANGE);

AddLabel(yes, "LONG Rate: " + AsPercent(win_rate), if win_rate > 0.666 then Color.DARK_GREEN else if win_rate < 0.333 then Color.DARK_RED else if win_rate > 0.5 then Color.BLUE else Color.DARK_ORANGE);

def short_trades = if !IsNaN(short) then if IsNaN(short_trades[1]) then 1 else short_trades[1] + 1 else short_trades[1];

def short_wins = if !IsNaN(short[win_length]) and close[win_length - 1] > close then if IsNaN(short_wins[1]) then 1 else short_wins[1] + 1 else short_wins[1];

def short_win_rate = short_wins / Max(short_trades, 1);

AddLabel(yes, "SHORT Rate: " + AsPercent(short_win_rate), if short_win_rate > 0.666 then Color.DARK_GREEN else if short_win_rate < 0.333 then Color.DARK_RED else if short_win_rate > 0.5 then Color.BLUE else Color.DARK_ORANGE);

# addChartBubble(short, low - (8 * tickSize()), text = short_wins + " / " + short_trades, if short_win_rate > 0.666 then color.green else if short_win_rate < 0.333 then color.red else if short_win_rate > 0.5 then color.cyan else color.orange, up = No);

# AddChartBubble("time condition" = short, "price location" = high + (4 * TickSize()), text = "S: " + Round(short_win_rate * 100, 0) + "%", color = if short_win_rate > 0.666 then Color.GREEN else if short_win_rate < 0.333 then Color.RED else if short_win_rate > 0.5 then Color.CYAN else Color.ORANGE);

def profit_loss = if !IsNaN(long[win_length]) then close[-1] - open[win_length - 1] else Double.NaN;

def pl_dollars = (profit_loss / TickSize()) * TickValue();
def time_to_pl = if !IsNaN(long[win_length]) then ( GetTime() - GetTime()[win_length]) / 60000 else Double.NaN;

# AddChartBubble("time condition" = !IsNaN(profit_loss), text = "P/L  $" + AbsValue(pl_dollars) + "\n" + time_to_pl + " min", "price location" = low - 4 * TickSize(), up = no, color = if pl_dollars > 0 then GlobalColor("pl_pos") else GlobalColor("pl_neg"));

Alert(condition = alerts == yes and long[1], text = "Long Entry", "alert type" = Alert.BAR, sound = Sound.Bell);
Alert(condition = alerts == yes and short[1], text = "Short Entry", "alert type" = Alert.BAR, sound = Sound.Bell);

def in_trade = if !IsNaN(EntryPrice()) then 1 else 0;
Alert(condition = alerts == yes and high crosses above target and in_trade == 1, text = "Target 1", "alert type" = Alert.BAR, sound = Sound.Ding);

Alert(condition = alerts == yes and high crosses above target2 and in_trade == 1, text = "Target 2", "alert type" = Alert.BAR, sound = Sound.Ring);

# AddLabel(yes, "Tick Stop Loss: " + (( trade_loss * tickSize() )/ tickValue()), color.gray);
AddLabel(yes, " SL/T: " + AsDollars(trade_loss) + "   R/Rs :  " + t1 + ",  " + t2 + "    ", Color.DARK_GRAY);

# AddChartBubble("time condition" = long[win_length], "price location" = SL, text = "LOSS = " + asDollars( (open[win_length] - lowest(LOW, win_length)) / ticksize() * tickValue()), up = No, color = GlobalColor("pl_neg"));

plot stoSell = stoch_sell;


def long_trail_stop =
    if !IsNaN(long[1])
        then open - (( trade_loss * TickSize() ) / TickValue())
    else if trade_length <= 60   
        then
            if high - (( trade_loss * TickSize() ) / TickValue()) > long_trail_stop[1]
                then high - (( trade_loss * TickSize() ) / TickValue())
            else
                long_trail_stop[1]
    else
        Double.NaN;


def short_trail_stop = if !IsNaN(short[1]) then open + (( trade_loss * TickSize() ) / TickValue()) else if trade_length <= 60 then if low + (( trade_loss * TickSize() ) / TickValue()) < short_trail_stop[1] then low + (( trade_loss * TickSize() ) / TickValue()) else short_trail_stop[1] else Double.NaN;

plot short_trail = short_trail_stop;
plot long_trail = long_trail_stop;

# def long_open = if !IsNaN(long[1]) or !IsNaN(short[1]) then open else if trade_length <= 60 then long_open[1] else Double.NaN;
# plot trade_open = long_open;

# addCloud(trade_open, long_trail, color.red, color.green);
# addCloud(trade_open, short_trail, color.green, color.red);

P.S. There is a bunch of code that's commented out in there, and I think I got all the proprietary stuff removed. (I have another version that uses the BuyTheDip indicator in conjunction with those herein). I can't remember what all of the variations of this script were designed to do. Things like "no cx" means it doesn't need to cross (presumably the previous one needed a crossover to trigger). I think the default settings work fairly well and you can probably safely ignore everything but the stop loss value and the R:R settings.

This will be my last big post for a while. I think.

-mashume
Looks very interesting so I set this up on one of my charts. I noted that this Worden did not take trading volume into account like some Wordens do...Perhaps way to complicated for TOS? But, I really love all the contributions you make to Think Script
 
Looks very interesting so I set this up on one of my charts. I noted that this Worden did not take trading volume into account like some Wordens do...Perhaps way to complicated for TOS? But, I really love all the contributions you make to Think Script
I trade this on tick charts, so volume is a non-issue for me. Worden is a method for using rank (of whatever variable you have in mind) to determine position within range. For volume, it would tell you where the last bar ranks over the length of the window. For close price, it tells you where the close ranks in that window. I like it because it acts as a filter on overly large or small movements.

-mashume
 
Great share. Thank you. Do you know if this indicator repaints on the upper chart?
 
Last edited:
Does this repaint on the upper chart?

Repainter Threads usually have a prefix of Repaints.
For prior candles, the calculations used in this indicator are set and final and do not repaint.

However, this study, like the majority of indicators on this forum, will continually update the current bar until it is closed.
Think about it, we can not know, as a candle is forming, what the final close, high, low, of the current bar is going to be, so of course, it updates with the most recent tick.

But continue to check it in live trading. Come back and relay your experience.
 
Last edited:

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
477 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