#// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
#// © faytterro
#strategy("Exponential Stochastic Strategy", overlay=false, default_qty_type=strategy.percent_of_equity, default_qty_value=100)
# -- Convered by Sam4Cok@Samer800 - 06/2024
declare lower;
input calcSource = {"Price",default "RSI"};
input length = 14; #, "length")
input ExponentialFactor = 2; #, title="exp", minval=1, maxval=10)
input smoothingType = AverageType.SIMPLE;
input smoothingLength = 3;
input overboughtLevel = 80;
input oversoldLevel = 20;
input labelOptions = {default "Summary", "Detailed", "Don't Show"};
input order_direction = {"Long", "Short",default "Long and Short"}; #, title = "Order Direction")
input exitTradeCondition = {Default "Auto Conditions", "Manual Conditions", "Both Conditions"}; # "TPSL Condition"
input entryExitLineDisplay = {Default "Enter Long/Short", "Exit Long/Short", "Both Entry/Exit", "Don't Show Lines"};
input lotSize = 15;
input takeProfitPercentage = 1.25; #, title="Take Profit (%)")
input stopLossPercentage = 0.5; #, title="Stop Loss (%)")
def na = Double.NaN;
def last = IsNaN(close);
def tpPer = takeProfitPercentage / 100;
def slPer = stopLossPercentage / 100;
def allSig = entryExitLineDisplay==entryExitLineDisplay."Both Entry/Exit";
def enter = entryExitLineDisplay==entryExitLineDisplay."Enter Long/Short" or allSig;
def exit = entryExitLineDisplay==entryExitLineDisplay."Exit Long/Short" or allSig;
def short = order_direction == order_direction."Short" or order_direction == order_direction."Long and Short";
def long = order_direction == order_direction."Long" or order_direction == order_direction."Long and Short";
def full = labelOptions == labelOptions."Detailed";
def summ = labelOptions == labelOptions."Summary" or full;
def Aut = exitTradeCondition == exitTradeCondition."Auto Conditions" or exitTradeCondition == exitTradeCondition."Both Conditions";
def man = exitTradeCondition == exitTradeCondition."Manual Conditions" or exitTradeCondition == exitTradeCondition."Both Conditions";
def nRSI = RSI(Price = close, Length = length);
def price = calcSource == calcSource."Price";
def srcHi = if price then high else nRSI;
def srcLo = if price then low else nRSI;
def src = if price then close else nRSI;
def expo = if ExponentialFactor < 10 then (ExponentialFactor) / (10 - ExponentialFactor) else 99;
def hh = Highest(srcHi, length);
def ll = Lowest(srcLo, length);
def s = 100 * (src - ll) / (hh - ll);
def ks = if s > 50 then Power(AbsValue(s - 50), expo) / Power(50, expo - 1) + 50 else
-Power(AbsValue(s - 50), expo) / Power(50, expo - 1) + 50;
def smKs = MovingAverage(smoothingType, ks, smoothingLength);
plot expStochLine = smKs; #, color= color.white)
expStochLine.SetLineWeight(2);
def bot = if last then na else oversoldLevel;
def top = if last then na else overboughtLevel;
AddCloud(100, top, Color.DARK_RED);
AddCloud(bot, 0, Color.DARK_GREEN);
#// Strategy logic
def movAvg = Average(src, 50);
def LongEntry = (smKs crosses above bot) and BarNumber() > 0;
def ShortEntry = (smKs crosses below top) and BarNumber() > 0;
def inTrades;
def entryLong;
def closeLong;
def entryShort;
def closeShort;
# getTrendBands(float src, float delta)=>
# "ATR Trend Bands [Misu]"
script getTrendBands {
input src = close;
input delta = 1;
def upperb;
def lowerb;
def low;
def upp;
if src > upperb[1] {
upperb = Max(upperb[1], Max(src, src[1]));
upp = upp[1];
low = upperb - delta;
lowerb = if (low < lowerb[1] or low > lowerb[1]) and upperb == upperb[1] then
lowerb[1] else low;
} else {
if src < lowerb[1] {
lowerb = Min(lowerb[1], Min(src, src[1]));
upp = lowerb + delta;
low = low[1];
upperb = if (upp > upperb[1] or upp < upperb[1]) and lowerb == lowerb[1] then
upperb[1] else upp;
} else {
upperb = upperb[1];
upp = upp[1];
low = low[1];
lowerb = lowerb[1];
}
}
def midb = (lowerb + upperb) / 2;
plot midLine = midb;
plot Upper = upperb;
plot Lower = lowerb;
}
#// ] -------- Logic ----------------- [
def tr = AbsValue(highest(src, 2) - lowest(src, 2));
def nATR = WildersAverage(tr, 10);
def deltaAtr = 2.6 * nATR;
def midb = getTrendBands(src, deltaAtr).midLine;
def upperb = getTrendBands(src, deltaAtr).Upper;
def lowerb = getTrendBands(src, deltaAtr).Lower;
def trendUp = midb > midb[1];
def trendDn = midb < midb[1];
def lastState = if trendUp then 1 else if trendDn then -1 else lastState[1];
def buyCond = trendUp and lastState[1] == -1; # and close>open;
def sellCond = trendDn and lastState[1] == 1; # and close<open;
def trade = if IsNaN(inTrades[1]) then 0 else inTrades[1];
def longCond = LongEntry and trade == 0 and long;
def shortCond = ShortEntry and trade == 0 and short;
def LcloseCond = buyCond and inTrades[1] > 0;
def ScloseCond = sellCond and inTrades[1] < 0;
def tpLvlLong = close * (1 + tpPer);
def slLvlLong = close * (1 - slPer);
def tpLvlShort = close * (1 - tpPer);
def slLvlShort = close * (1 + slPer);
def manExitLong = ((entryLong[1] >= tpLvlLong) or (entryLong[1] < slLvlLong)) and trade > 0;
def manExitShort = ((entryShort[1] <= tpLvlShort) or (entryShort[1] > slLvlShort)) and trade < 0;
def exitLong;
def exitShort;
switch (exitTradeCondition) {
case "Manual Conditions" :
exitLong = manExitLong;
exitShort = manExitShort;
case "Both Conditions" :
exitLong = manExitLong or LcloseCond;
exitShort = manExitShort or ScloseCond;
default :
exitLong = LcloseCond;
exitShort = ScloseCond;
}
def inPrice = open[-1];
if longCond {
inTrades = 1;
entryLong = inPrice;
entryShort = entryShort[1];
closeLong = 0;
closeShort = 0;
} else if exitLong {
inTrades = 0;
entryLong = entryLong[1];
entryShort = entryShort[1];
closeLong = inPrice - entryLong;
closeShort = 0;
} else if shortCond {
inTrades = -1;
entryLong = entryLong[1];
entryShort = inPrice;
closeLong = 0;
closeShort = 0;
} else if exitShort {
inTrades = 0;
entryLong = entryLong[1];
entryShort = entryShort[1];
closeLong = 0;
closeShort = entryShort - inPrice;
} else {
inTrades = trade;
entryLong = if IsNaN(entryLong[1]) then 0 else entryLong[1];
entryShort = if IsNaN(entryShort[1]) then 0 else entryShort[1];
closeLong = 0;
closeShort = 0;
}
#def tot1 = inTrades;
def longSig = inTrades == 1 and inTrades[1] != 1;
def shortSig = inTrades == -1 and inTrades[1] != -1;
def exitL = inTrades == 0 and inTrades[1] == 1;
def exitS = inTrades == 0 and inTrades[1] == -1;
def totLong = TotalSum(if exitL then 1 else 0);
def totShort = TotalSum(if exitS then 1 else 0);
def tottrd = totLong + totShort;
def tradeL = Sign(closeLong);
def tradeS = Sign(closeShort);
def WinL = TotalSum(if tradeL > 0 then 1 else 0);
def WinS = TotalSum(if tradeS > 0 then 1 else 0);
def totWin = (WinL + WinS);
def winRt = Round(totWin / tottrd * 100, 1);
def winRtL = Round(WinL / totLong * 100, 1);
def winRtS = Round(WinS / totShort * 100, 1);
def amtL = TotalSum(if exitLong then closeLong else 0) * lotSize;
def amtS = TotalSum(if exitShort then closeShort else 0) * lotSize;
def pl = RoundDown(amtL + amtS, 2);
def plL = RoundDown(amtL, 2);
def plS = RoundDown(amtS, 2);
plot entLong = if longCond then -3 else na;
plot entShort = if shortCond then 103 else na;
entLong.SetPaintingStrategy(PaintingStrategy.SQUARES);
entShort.SetPaintingStrategy(PaintingStrategy.SQUARES);
entLong.SetDefaultColor(Color.GREEN);
entShort.SetDefaultColor(Color.RED);
expStochLine.AssignValueColor(if lastState>0 then Color.LIGHT_GREEN else if lastState<0 then Color.PINK else Color.GRAY);
AddVerticalLine(exit and exitLong, "Exit L", Color.CYAN);
AddVerticalLine(exit and exitShort, "Exit S", Color.MAGENTA);
AddLabel(summ, "WinRate(" + winRt + "%," + totWin + "/" + tottrd + ")", if winRt >= 50 then Color.GREEN else Color.RED);
AddLabel(full and long, "Long(" + winRtL + "%," + WinL + "/" + totLong + ")", if winRtL >= 50 then Color.GREEN else Color.RED);
AddLabel(full and short, "Short(" + winRtS + "%," + WinS + "/" + totShort + ")", if winRtS >= 50 then Color.GREEN else Color.RED);
AddLabel(full and long, "AmtLong($" + plL + ")", if amtL > 0 then Color.GREEN else Color.RED);
AddLabel(full and short, "AmtShort($" + plS + ")", if amtS > 0 then Color.GREEN else Color.RED);
AddLabel(summ, "P/L($" + pl + ")", if pl > 0 then Color.GREEN else if pl < 0 then Color.RED else Color.GRAY);
AddLabel(full, "InTrade: " + (if inTrades>0 then "Long" else if inTrades<0 then "Short" else "No"),
if inTrades>0 then Color.GREEN else if inTrades<0 then Color.RED else Color.GRAY);
#-- END of CODE