#JT Newest Strategy Based on EMAs, TSI, Premarket Highs/Lows, and MACD
#VERSION 8 - 04/21/2022
#Notes
#Added The Ability to Turn Off PreMarket High/Low Cloud
#Added Labels for PreMarket High/Low with Ability to Turn On/Off
#Changed the Global Color of Tk Pft to Pink
#Added the ablity of Background Color Change to Match Bubble (Used in FlexGrid), Default if Off.
#Added different time frames. This controls the EMA Seperation Threshold and Last Sell Candle.
Declare Upper;
##################################################################
# TIMES #
##################################################################
#START AND END TIMES
input TimeFrame = {default "10-Min", "1-Min", "5-Min", "15-Min", "30-Min", "1-Hour"};
input PreMarketStart = 0730; #EST
input PreMarketEnd = 0929; #EST
input StartTime = 0930; #EST
input BuySignalDelay = 29;
input EndTime = 1600; #EST
input BuySignalStop = 60; #Minutes Before End of Day
def LastCandleStop; #Last Candle is Sell Candle
switch (TimeFrame) {
case "1-min": LastCandleStop = 1;
case "5-Min": LastCandleStop = 5;
case "15-Min": LastCandleStop = 15;
case "30-Min": LastCandleStop = 30;
case "1-Hour": LastCandleStop = 60;
default: LastCandleStop = 10;
}
def TradingDayStart= SecondsFromTime(StartTime);
def BuySignalDelaySeconds = BuySignalDelay * 60;
def SignalStart = TradingDayStart > BuySignalDelaySeconds;
def TradingDayEnd = SecondsTillTime(EndTime);
def EndSignalDelaySeconds = BuySignalStop * 60;
def SignalEnd = TradingDayEnd > EndSignalDelaySeconds;
def TradingDay = SignalStart and SignalEnd; #10:00EST - 1500EST
def LastStopDelaySeconds = LastCandleStop * 60;
def EndDay = TradingDayEnd == LastStopDelaySeconds; #1550EST
def TradingDayExt = TradingDayEnd > LastStopDelaySeconds;
##################################################################
# INDICATORS #
##################################################################
input ShowTestBubbles = no;
#EMAS
input Ema1Length = 5;
input Ema2Length = 12;
input Ema3Length = 34;
input Ema4Length = 50;
#input Ema5Length = 8; #If Needed
#input Ema6LEngth = 9; #If Needed
plot FastEMA1 = ExpAverage(close, Ema1Length);
FastEMA1.SetDefaultColor(color.light_green);
FastEMA1.HideBubble();
plot FastEMA2 = ExpAverage(close, Ema2Length);
FastEMA2.SetDefaultColor(color.light_red);
FastEMA2.HideBubble();
AddCloud(FastEMA1, FastEMA2, createcolor(0, 255, 153), createcolor(0, 153, 255));
plot SlowEMA1 = ExpAverage(close, Ema3Length);
SlowEMA1.SetDefaultColor(color.light_green);
SlowEMA1.HideBubble();
plot SlowEMA2 = ExpAverage(close, Ema4Length);
SlowEMA2.SetDefaultColor(color.light_red);
SlowEMA2.HideBubble();
AddCloud(SlowEMA1, SlowEMA2, createcolor(0, 255, 0), createcolor(0, 0, 255));
#def FastEMA3 = ExpAverage(close, EMA5Length); #If Needed
#def FastEMA4 = ExpAverage(close, EMA6Length); #If Needed
#AddCloud(FastEMA3, FastEMA4, Color.light_gray, Color.light_gray); #If Needed
#EMAS BULLISH OR BEARISH
def FastEMABullish = FastEMA1 > FastEMA2;
def SlowEMABullish = SlowEMA1 > SlowEMA2;
def FastEMABearish = FastEMA1 < FastEMA2;
def SlowEMABearish = SlowEMA1 < SlowEMA2;
#EMA BUY SIGNAL
def BothEMASBullish = FastEMABullish and SlowEMABullish;
def BothEMASBearish = FastEMABearish and SlowEMABearish;
#EMA PERCENT SEPERATION
def FastEMAPctBull = ((FastEMA1 / FastEMA2) * 100) - 100; #Distance Between Fast EMA 1 and Fast EMA 2
def FastEMAPctBullRound = Round(FastEMAPctBull, 2);
def FastEMAPctBear = ((FastEMA2 / FastEMA1) * 100) - 100; #Distance Between Fast EMA 2 and Fast EMA 1
def FastEMAPctBearRound = Round(FastEMAPctBear, 2);
#FAST EMA PERCENT SEPERATION BUY SIGNAL
def EMASepThrHld;
switch (TimeFrame) {
case "1-min": EMASepThrHld = 0.1;
case "5-Min": EMASepThrHld = 0.2;
case "15-Min": EMASepThrHld = 0.3;
case "30-Min": EMASepThrHld = 0.4;
case "1-Hour": EMASepThrHld = 0.1;
default: EMASepThrHld = 0.25;
}
def FastEMAPctBullish = BothEMASBullish and FastEMAPctBullRound > EMASepThrHld and FastEMAPctBullRound >= FastEMAPctBullRound[1];
def FastEMAPctBearish = BothEMASBearish and FastEMAPctBearRound > EMASepThrHld and FastEMAPctBearRound >= FastEMAPctBearRound[1];
#TESTING
addchartbubble(if ShowTestBubbles and FastEMAPctBullish == 1 then 1 else 0, SlowEMA2*0.995, FastEMAPctBullRound, color.dark_green, no);
addchartbubble(if ShowTestBubbles and FastEMAPctBearish == 1 then 1 else 0, SlowEMA2*1.005, FastEMAPctBearRound, color.dark_green, yes);
def SlowEMAPctBull = ((SlowEMA1 / SlowEMA2) * 100) - 100; #Distance Between Slow EMA 1 and Slow EMA 2
def SlowEMAPctBullRound = Round(SlowEMAPctBull, 2);
def SlowEMAPctBear = ((SlowEMA2 / SlowEMA1) * 100) - 100; #Distance Between Slow EMA 1 and Slow EMA 2
def SlowEMAPctBearRound = Round(SlowEMAPctBear, 2);
#SLOW EMA PERCENT SEPERATION BULLISH
def SlowEMAPctBullish = BothEMASBullish and SlowEMAPctBullRound >= SlowEMAPctBullRound[1];
def SlowEMAPctBearish = BothEMASBearish and SlowEMAPctBearRound <= SlowEMAPctBearRound[1];
#EMA SELL SIGNALS
def FastEMACrossDown = FastEMA1 crosses below FastEMA2;
def FastEMACrossUp = FastEMA1 crosses above FastEMA2;
def FastEMAPctBullDecrease = if BothEMASBullish and FastEMAPctBullRound < (FastEMAPctBullRound[1] * 0.75) then 1 else 0;
def FastEMAPctBearDecrease = if BothEMASBearish and FastEMAPctBearRound < (FastEMAPctBearRound[1] * 0.75) then 1 else 0;
#TESTING
addchartbubble(if ShowTestBubbles and FastEMAPctBullDecrease == 1 then 1 else 0, SlowEMA2*0.995, FastEMAPctBullRound, color.dark_red, no);
addchartbubble(if ShowTestBubbles and FastEMAPctBearDecrease == 1 then 1 else 0, SlowEMA2*1.005, FastEMAPctBearRound, color.dark_red, yes);
#SLOWEMA2 SLOPE (NOT USING AT THIS TIME)
def Height = SlowEMA2 - SlowEMA2[11];
def SlopeDeg = Round((ATan(Height / 10) * 180 / Double.Pi), 0);
#SLOWEMA2 SLOPE SELL SIGNAL
def BullSlopeSell = BothEMASBullish and SlopeDeg < SlopeDeg[1];
def BearSlopeSell = BothEMASBearish and SlopeDeg > SlopeDeg[1];
#TESTING
#addchartbubble(if ShowTestBubbles and BullSlopeSell == 1 then 1 else 0, SlowEMA2*0.995, "Slope", color.dark_red, no);
#addchartbubble(if ShowTestBubbles and BearSlopeSell == 1 then 1 else 0, SlowEMA2*1.005, "Slope", color.dark_red, yes);
#MACD
input MACDFast = 10;
input MACDSlow = 22;
input MACDLength = 8;
def MACDValue = ExpAverage(close, MACDFast) - ExpAverage(close, MACDSlow);
def MACDAverage = ExpAverage(MACDValue, MACDLength);
def MACDDiff = MACDValue - MACDAverage;
def ZeroLine = 0;
#MACD BUY SIGNAL
def MACDBull = MACDDiff >= MACDDiff[1];
def MACDBear = MACDDiff <= MACDDiff[1];
#MACD SELL SIGNAL
#No Sell SIgnals At This Time
#TSI
input TSILongLength = 25;
input TSIShortLength = 13;
input TSISignalLength = 8;
def TSIDiff = close - close[1];
def DoubleSmoothedAbsDiff = ExpAverage(ExpAverage(AbsValue(TSIDiff), TSILongLength), TSIShortLength);
def TSIRound = Round((100 * (ExpAverage(ExpAverage(TSIDiff, TSILongLength), TSIShortLength)) / DoubleSmoothedAbsDiff), 2);
#TSI BUY SIGNAL
def TSIBull = (TSIRound > 10) and (TSIRound >= TSIRound[1]);
def TSIBear = (TSIRound < -10) and (TSIRound <= TSIRound[1]);
#TSI SELL SIGNAL
def TSICrossDown = TSIRound < (TSIRound[1] * 0.91);
def TSICrossUp = TSIRound > (TSIRound[1] * 0.91);
#TSI TAKE PROFIT
#No TSI Take Profit At This Time
#PREMARKET HIGHS AND LOWS
input ShowPreMarketCloud = yes;
input ShowPreMarketLabel = yes;
def PreMarketTimeRange = secondsFromTime(PreMarketStart) >= 0 and secondsTillTime(PreMarketEnd) >= 0;
def PreMarket = PreMarketTimeRange and !PremarketTimeRange[1];
def Pre_Market_High = compoundValue(1, if((high > Pre_Market_High[1] and PremarketTimeRange) or PreMarket, high, Pre_Market_High[1]), high);
def Pre_Market_Low = compoundValue(1, if((low < Pre_Market_Low[1] and PremarketTImeRange) or PreMarket, low, Pre_Market_Low[1]), low);
plot PreMarketHigh = if ShowPreMarketCloud then Pre_Market_High else double.nan;
PreMarketHigh.SetStyle(curve.short_dash);
PreMarketHigh.SetDefaultColor(color.light_gray);
PreMarketHigh.setLineWeight(1);
plot PreMarketLow = if ShowPreMarketCloud then Pre_Market_Low else double.nan;
PreMarketLow.SetStyle(curve.short_dash);
PreMarketLow.SetDefaultColor(color.light_gray);
PreMarketLow.setLineWeight(1);
AddCloud (PreMarketHigh, PreMarketLow, color.light_gray, color.light_gray);
AddLabel(if ShowPreMarketLabel then yes else no, " ", color.black);
AddLabel(if ShowPreMarketLabel then yes else no, " PM High - $" + PreMarketHigh, color.gray);
AddLabel(if ShowPreMArketLabel then yes else no, " PM Low - $" + PreMarketLow, color.gray);
#PREMARKET HIGH/LOW BUY SIGNAL
def PreMarketBull = low > Pre_Market_High;
def PreMarketBear = high < Pre_Market_Low;
#TESTING
addchartbubble(if ShowTestBubbles and PreMarketBull == 1 then 1 else 0, SlowEMA2*0.995, "Pre", color.dark_green, no);
addchartbubble(if ShowTestBubbles and PreMarketBear == 1 then 1 else 0, SlowEMA2*1.005, "Pre", color.dark_green, yes);
#PREMARKET HIGH/LOW SELL SIGNAL
def PreMarketBullSell = PreMarketBull[1] and low < Pre_Market_High;
def PreMarketBearSell = PreMarketBear[1] and high > Pre_Market_Low;
#TESTING
addchartbubble(if ShowTestBubbles and PreMarketBullSell == 1 then 1 else 0, SlowEMA2*0.995, "Pre", color.dark_red, no);
addchartbubble(if ShowTestBubbles and PreMarketBearSell == 1 then 1 else 0, SlowEMA2*1.005, "Pre", color.dark_red, yes);
##################################################################
# SIGNALS #
##################################################################
#GET READY
def GetReadyBull = TradingDay and BothEMASBullish and PreMarketBull;
def GetReadyBear = TradingDay and BothEMASBearish and PreMarketBear;
#INDICATOR BUY SIGNALS
def CallBuyInd = BothEMASBullish and FastEMAPctBullish and MACDBull and TSIBull and PreMarketBull;
def PutBuyInd = BothEMASBearish and FastEMAPctBearish and MACDBear and TSIBear and PreMarketBear;
#TESTING
addchartbubble(if ShowTestBubbles and CallBuyInd == 1 then 1 else 0, SlowEMA2*0.995, "C-Ind", color.light_green, no);
addchartbubble(if ShowTestBubbles and PutBuyInd == 1 then 1 else 0, SlowEMA2*1.005, "P-Ind", color.light_green, yes);
##################################################################
# ADDED FAST EMA PCT HERE BASED OFF BUY SIGNAL #
##################################################################
def EMAPctAtCallBuy = if CallBuyInd then FastEMAPctBullRound else EMAPctAtCallBuy[1]; #Used to Calculate Sell Trigger
def EMAPctAtPutBuy = if PutBuyInd then FastEMAPctBearRound else EMAPctAtPutBuy[1]; #Used to Calculate Sell Trigger
#FAST EMA CLOUD SELL TRIGGER BASED OFF BUY INDICATOR
def CallEMAPctSell = FastEMAPctBullRound < EMAPctAtCallBuy * 0.65;
def PutEMAPctSell = FastEMAPctBearRound < EMAPctAtPutBuy * 0.65;
##################################################################
# SIGNALS CONT. #
##################################################################
#INDICATOR HOLD SIGNALS
def CallHoldInd = BothEMASBullish and PreMarketBull;
def PutHoldInd = BothEMASBearish and PreMarketBear;
#TESTING
addchartbubble(if ShowTestBubbles and CallHoldInd == 1 then 1 else 0, SlowEMA2*0.995, "CH_Ind", color.light_green, no);
addchartbubble(if ShowTestBubbles and PutHoldInd == 1 then 1 else 0, SlowEMA2*1.005, "PH-Ind", color.light_green, yes);
##################################################################
# EMA TAKE PROFIT CLOUD (IDENTIFY IF PRICE IS EXTENDED FROM EMAS)#
##################################################################
input ShowOverExtCloud = yes;
def OvrExtUp1 = if ShowOverExtCloud and SignalStart and TradingDayExt and (CallBuyInd or CallHoldInd) then FastEMA1 * 1.01 else Double.NaN;
#addchartbubble(if High > OvrExtUp1 == 1 then 1 else 0, OvrExtUp1*1.005, "TkPft1", color.light_green, yes);
def OvrExtUp2 = if ShowOverExtCloud and SignalStart and TradingDayExt and (CallBuyInd or CallHoldInd) then FastEMA1 * 1.02 else Double.NaN;
#addchartbubble(if High > OvrExtUp2 == 1 then 1 else 0, OvrExtUp2*1.005, "TkPft2", color.light_green, yes);
AddCloud(OvrExtUp1, OvrExtUp2, color.light_green, color.light_green);
def OvrExtDn1 = if ShowOverExtCloud and SignalStart and TradingDayExt and (PutBuyInd or PutHoldInd) then FastEMA1 * 0.99 else Double.NaN;
#addchartbubble(if Low < OvrExtDn1 == 1 then 1 else 0, OvrExtDn1*0.995, "TkPft1", color.light_green, no);
def OvrExtDn2 = if ShowOverExtCloud and SignalStart and TradingDayExt and (PutBuyInd or PutHoldInd) then FastEMA1 * 0.98 else Double.NaN;
#addchartbubble(if Low < OvrExtDn2 == 1 then 1 else 0, OvrExtDn2*0.995, "TkPft2", color.light_green, no);
AddCloud(OvrExtDn1, OvrExtDn2, color.light_green, color.light_green);
##################################################################
# SIGNALS CONT. #
##################################################################
#INDICATOR SELL SIGNALS
def CallSellInd = FastEMACrossDown or TSICrossDown or CallEMAPctSell;
def PutSellInd = FastEMACrossUp or TSICrossUp or PutEMAPctSell;
#TESTING
addchartbubble(if ShowTestBubbles and CallSellInd == 1 then 1 else 0, SlowEMA2*0.995, "CS-Ind", color.light_red, no);
addchartbubble(if ShowTestBubbles and PutSellInd == 1 then 1 else 0, SlowEMA2*1.005, "PS-Ind", color.light_red, yes);
#BUY SIGNALS
def CallBuy = TradingDay and CallBuyInd;
def PutBuy = TradingDay and PutBuyInd;
#TESTING
addchartbubble(if ShowTestBubbles and CallBuy == 1 then 1 else 0, SlowEMA2*0.995, "Call", color.green, no);
addchartbubble(if ShowTestBubbles and PutBuy == 1 then 1 else 0, SlowEMA2*1.005, "Put", color.green, yes);
#HOLD SIGNALS
def CallHold = TradingDayExt and CallHoldInd and (CallBuy[1] or CallHold[1]);
def PutHold = TradingDayExt and PutHoldInd and (PutBuy[1] or PutHold[1]);
#TESTING
addchartbubble(if ShowTestBubbles and CallHold == 1 then 1 else 0, SlowEMA2*0.995, "C-Hold", color.green, no);
addchartbubble(if ShowTestBubbles and PutHold == 1 then 1 else 0, SlowEMA2*1.005, "P-Hold", color.green, yes);
#SELL SIGNALS
def CallSell = TradingDayExt and CallSellInd and !CallSellInd[1] and (CallBuy[1] or CallHold[1]);
def PutSell = TradingDayExt and PutSellInd and !PutSellInd[1] and (PutBuy[1] or PutHold[1]);
#TESTING
addchartbubble(if ShowTestBubbles and CallSell == 1 then 1 else 0, SlowEMA2*0.995, "C-Sell", color.red, no);
addchartbubble(if ShowTestBubbles and PutSell == 1 then 1 else 0, SlowEMA2*1.005, "P-Sell", color.red, yes);
##################################################################
# BARS #
##################################################################
DefineGlobalColor("OpenLongPosition", createcolor (0, 255, 0));
DefineGlobalColor("OpenShortPosition", createcolor (0, 0, 255));
DefineGlobalColor("HoldLongPosition", createcolor (204, 255, 204));
DefineGlobalColor("HoldShortPosition", createcolor (102, 255, 255));
DefineGlobalColor("GetReady", createcolor (204, 153, 0));
DefineGlobalColor("SellPosition", createcolor (255, 0, 0));
DefineGlobalColor("TakeProfit", createcolor (255, 0, 255));
DefineGlobalColor("CriteriaNotMet", createcolor (102, 102, 102));
#COLOR BARS
AssignPriceColor(if CallSell then GlobalColor("SellPosition") else if CallBuy then GlobalColor("OpenLongPosition") else if CallHold then GlobalColor("HoldLongPosition") else if PutSell then GlobalColor("SellPosition") else if PutBuy then GlobalColor("OpenShortPosition") else if PutHold then GlobalColor("HoldShortPosition") else if EndDay then GlobalColor("SellPosition") else if GetReadyBull then GlobalColor("GetReady") else if GetReadyBear then GlobalColor("GetReady") else GlobalColor("CriteriaNotMet"));
##################################################################
# LABELS #
##################################################################
#LABELS
AddLabel(yes, " ", color.black);
AddLabel(yes, "PREMKT", if PreMarketBull then GlobalColor("OpenLongPosition") else if PreMarketBear then GlobalColor("OpenShortPosition") else color.gray);
AddLabel(yes, "CLOUDS", if BothEMASBullish then GlobalColor("OpenLongPosition") else if BothEMASBearish then GlobalColor("OpenShortPosition") else color.gray);
AddLabel(yes, "EMA SEP", if FastEMAPctBullish then GlobalColor("OpenLongPosition") else if FastEMAPctBearish then GlobalColor("OpenShortPosition") else color.gray);
AddLabel(yes, "TSI", if TSIBull then GlobalColor("OpenLongPosition") else if TSIBear then GlobalColor("OpenShortPosition") else color.gray);
AddLabel(yes, "MACD", if MACDBull then GlobalColor("OpenLongPosition") else if MACDBear then GlobalColor("OpenShortPosition") else color.gray);
##################################################################
# CHART BUBBLES FOR BUY/SELL #
##################################################################
input ShowBuySellBubbles = Yes;
input ShowTkPftBubble = Yes;
#BUY
def CallBuyBub = TradingDay and !CallSell and (CallBuy[1] or CallBuy[2] or CallBuy[3]) and low <= FastEMA1 and low >= FastEMA2;
addchartbubble(ShowBuySellBubbles and CallBuybub, low * 0.999, "Long", GlobalColor("OpenLongPosition"), no);
def PutBuyBub = TradingDay and !PutSell and (PutBuy[1] or PutBuy[2] or PutBuy[3]) and high >= FastEMA1 and high <=FastEMA2;
addchartbubble(ShowBuySellBubbles and PutBuyBub, high * 1.001, "Short", GlobalColor("OpenShortPosition"), yes);
#SELL
def CallSellBub = TradingDayExt and (CallBuy[1] or CallHold[1]) and CallSell;
addchartbubble(ShowBuySellBubbles and CallSellBub, low * 0.999, "Sell", GlobalColor("SellPosition"), no);
def PutSellBub = TradingDayExt and (PutBuy[1] or PutHold[1]) and PutSell;
addchartbubble(ShowBuySellBubbles and PutSellBub, high * 1.001, "Sell", GlobalColor("SellPosition"), yes);
#TAKE PROFIT
def TkPftBubCall = TradingDayExt and (CallBuyInd or CallHoldInd) and high > FastEMA1 * 1.01;
addchartbubble(ShowBuySellBubbles and ShowTkPftBubble and TkPftBubCall, high * 1.001, "Tk Pft", GlobalColor("TakeProfit"), yes);
def TkPftBubPut = TradingDayExt and (PutBuyInd or PutHoldInd) and low < FastEMA1 * 0.99;
addchartbubble(ShowBuySellBubbles and ShowTkPftBubble and TkPftBubPut, low * 0.999, "Tk Pft", GlobalColor("TakeProfit"), no);
##################################################################
# ORDERS #
##################################################################
#ORDERS
input ShowOrders = no;
#BUY ORDERS
AddOrder(OrderType.BUY_TO_OPEN, ShowOrders and (CallBuy[1] or CallBuy[2])or CallBuy[3] and low <= FastEMA1 and low >= FastEMA2, FastEMA1, 100, Color.GREEN, Color.LIGHT_GREEN);
AddOrder(OrderType.SELL_TO_OPEN, ShowOrders and (PutBuy[1] or PutBuy[2] or PutBuy[3]) and high >= FastEMA1 and high <=FastEMA2, FastEMA1, 100, Color.GREEN, Color.LIGHT_GREEN);
#SELL ORDERS
AddOrder(OrderType.SELL_TO_CLOSE, ShowOrders and TkPftBubCall, high * 0.999, 100, Color.RED, Color.LIGHT_RED);
AddOrder(OrderType.SELL_TO_CLOSE, ShowOrders and CallSellBub or EndDay[-1], close, 100, Color.RED, Color.LIGHT_RED);
AddOrder(OrderType.BUY_TO_CLOSE, ShowOrders and TkPftBubPut, low * 1.001, 100, Color.RED, Color.LIGHT_RED);
AddOrder(OrderType.BUY_TO_CLOSE, ShowOrders and PutSellBub or EndDay[-1], close, 100, Color.RED, Color.LIGHT_RED);
##################################################################
# ALERTS #
##################################################################
#ALERTS
input AlertOn = yes;
Alert(AlertOn and (CallSellBub or PutSellBub or TkPftBubCall or TkPftBubPut), "SELL", Alert.BAR, Sound.Bell);
Alert(AlertOn and (CallBuyBub or PutBuyBub), "BUY", Alert.BAR, Sound.Chimes);
##################################################################
# PROFIT/LOSS LABEL #
##################################################################
input ShowPLLabel = Yes;
#CALL
AddLabel(if ShowPLLabel then yes else no, " ", color.black);
def CallOpen = if CallBuy and !CallHold then FastEMA1 else CallOpen[1];
def CallEnd = if TkPftBubCall then high * 0.999 else if CallSellBub then close else CallEnd[1];
def CallOpenCost = CallOpen * 100;
def CallCloseCost = CallEnd * 100;
def CallDiff = round(CallCloseCost - CallOpenCost, 2);
AddLabel(if ShowPLLabel then yes else no, "Long Trade P/L - $ " + CallDiff + " ", if CallDiff > 0 then color.light_green else if CallDiff < 0 then color.light_red else color.gray);
#PUT
def PutOpen = if PutBuy and !PutHold then FastEMA1 else PutOpen[1];
def PutEnd = if TkPftBubPut then low * 1.001 else if PutSellBub then close else PutEnd[1];
def PutOpenCost = PutOpen * 100;
def PutCloseCost = PutEnd * 100;
def PutDiff = round(PutOpenCost - PutCloseCost, 2);
AddLabel(if ShowPLLabel then yes else no, "Short Trade P/L - $ " + PutDiff + " ", if PutDiff > 0 then color.light_green else if PutDiff < 0 then color.light_red else color.gray);
##################################################################
# CANDLE COLOR LABEL #
##################################################################
#LABELS
input ShowColorDefLabels = yes;
AddLabel(if ShowColorDefLabels == 1 then yes else no, " ", color.black);
AddLabel(if ShowColorDefLabels == 1 then yes else no, "Long Ind", GlobalColor("OpenLongPosition"));
AddLabel(if ShowColorDefLabels == 1 then yes else no, "Long Hld", GlobalColor("HoldLongPosition"));
AddLabel(if ShowColorDefLabels == 1 then yes else no, "Short Ind", GlobalColor("OpenShortPosition"));
AddLabel(if ShowColorDefLabels == 1 then yes else no, "Short Hld", GlobalColor("HoldShortPosition"));
AddLabel(if ShowColorDefLabels == 1 then yes else no, "Get Ready", GlobalColor("GetReady"));
AddLabel(if ShowColorDefLabels == 1 then yes else no, "Sell", GlobalColor("SellPosition"));
AddLabel(if ShowColorDefLabels == 1 then yes else no, "Tk Pft", GlobalColor("TakeProfit"));
AddLabel(if ShowColorDefLabels == 1 then yes else no, "No Criteria", GlobalColor("CriteriaNotMet"));
##################################################################
# BACKGROUND COLOR FOR FLEX GRID #
##################################################################
#BACKGROUND
input ShowFlexGridBackgroundColor = no;
AssignBackgroundColor(if ShowFlexGridBackgroundColor and (CallSellBub or PutSellBub) then GlobalColor("SellPosition") else if CallBuyBub then GlobalColor("OpenLongPosition") else if PutBuyBub then GlobalColor("OpenShortPosition") else if ShowFlexGridBackgroundColor and TradingDayExt and (CallBuyInd or CallHoldInd) and (TkPftBubCall or TkPftBubPut) then GlobalColor("TakeProfit") else color.current);
############################
# FPL Extended
# Extended Floating P&L study.
# Author: Eddielee394
# Version: 1.2
# inspired by FPL Dashboard script developed by Mobius
#
############################
#Hint: An extended floating P&L study to be used alongside TOS strategies for measuring hypothetical strategy performance.\nThis is a work in progress. And may contain some bugs or other programming issues.
############################
# Instructions
# - Due to limitations with the thinkscript public api, this specific script must be added to a "strategy" study.
# Generally best practice is to append this script to the end of your custom strategy (ensuring it runs AFTER the
# AddOrder() function is called from the strategy). A better method would be to use as a lower study but unless
# a workaround is implemented to handle the Entry() function in a lower study, it can only be applied to upper strategies.
#
# - the script uses the HidePrice() function which will hide the actual price candles within the upper study,
# only displaying the FPL histogram.
#
############################
############################
# Metrics
# - Active Trade return %
# - Entry Count
# - Winning Entry Count
# - Win rate
# - Avg return
# - avg win
# - avg loss
# - peak to valley dd
# - largest equity dd
# - P&L low
# - P&L high
# - Highest return
# - Lowest return
############################
############################
# Todo:
# - Sharpe Ratio
# - Sortino Ratio
# - Calmar Ratio
# - Avg trade
# duration
# -Buy/hold comparison
############################
#Globals
def nan = Double.NaN;
def bn = if !IsNaN(close) and !IsNaN(close[1]) and !IsNaN(close[-1]) then BarNumber() else bn[1];
#Inputs
input fplBegin = 0000;
#hint fplBegin: start time: the time in which then dailyHighLow profit should consider the day start. Recommended value is 0000.
input fplTargetWinLoss = .50;
#hint fplTargetWinLoss: sets the target winlossRatio (in percent) which determines display colors of the W/L label.
input fplTargetWinRate = 1;
#hint fplTargetWinRate: sets the target winRate (float) which determines display colors of the WinRate label;
input fplHidePrice = no;
#hint fplHidePrice: hide's the underlying price graph. \nDefault is no.
input fplHideFPL = yes;
#hint fplHideFPL: hide's the underlying P&L graph.\nDefault is yes.
input fplShowEntryBubbles = no;
#hint fplShowEntryBubbles: display bubbles on the FPL showing the entry and exit P&L values
input fplEnableDebugging = no;
#hint fplEnableDebugging: displays various debugging labels and chart bubbles. \nIt's recommended to hide the price chart & set the fpl hide fpl setting to yes, when enabling.
#temp input var references
def begin = fplBegin;
def targetWinLoss = fplTargetWinLoss;
def targetWinRate = fplTargetWinRate;
def hidePrice = fplHidePrice;
def hideFPL = fplHideFPL;
def showEntryBubbles = fplShowEntryBubbles;
def enableDebugging = fplEnableDebugging;
#hide chart candles
HidePricePlot(hidePrice);
#Plot default Floating P&L
plot FPL = FPL();
FPL.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
FPL.DefineColor("Positive and Up", Color.GREEN);
FPL.DefineColor("Positive and Down", Color.DARK_GREEN);
FPL.DefineColor("Negative and Down", Color.RED);
FPL.DefineColor("Negative and Up", Color.DARK_RED);
FPL.AssignValueColor(if FPL >= 0
then if FPL > FPL[1]
then FPL.Color("Positive and Up")
else FPL.Color("Positive and Down")
else if FPL < FPL[1]
then FPL.Color("Negative and Down")
else FPL.Color("Negative and Up"));
FPL.SetHiding(hideFPL);
plot ZeroLine1 = if IsNaN(close)
then nan
else 0;
ZeroLine1.SetDefaultColor(Color.GRAY);
ZeroLine1.SetHiding(hideFPL);
#Global Scripts
script calculateDrawdown {
input plLow = 1;
input plHigh = 1;
def _drawdown = if plHigh == 0
then 0 #handles the divide by zero error
else (plLow - plHigh) / plHigh;
plot calculateDrawdown = _drawdown;
}
script incrementValue {
input condition = yes;
input increment = 1;
input startingValue = 0;
def _value = CompoundValue(1,
if condition
then _value[1] + increment
else _value[1], startingValue);
plot incrementValue = _value;
}
;
script getDurationInMins {
input gdimBarCount = 1;
#get the aggregation period (MS per bar)
def aggPeriod = GetAggregationPeriod();
#multiply length of bars by aggPeriod to determine total milliseconds then convert to minutes
def _getDurationInMins = Floor((gdimBarCount * aggPeriod) / 60000);
plot getDurationInMins = _getDurationInMins;
}
script formatDuration {
input fdBarCount = 1;
def _fdDuration = getDurationInMins(fdBarCount);
def _formatDuration = if _fdDuration >= 60 and _fdDuration < 1440 #hours but not days
then 1
else if _fdDuration >= 1440 #days
then 2
else 0;
plot formatDuration = _formatDuration;
}
script calculateDuration {
input cdBarCount = 1;
def _cdDurationFormat = formatDuration(cdBarCount);
def _cdDuration = getDurationInMins(cdBarCount);
#if minutes > hour convert to hour, else if minutes > day, then convert to days
def _calculateDuration = if _cdDurationFormat == 1
then _cdDuration / 60 #convert to hours if greater than 60min but less than a day (1440)
else if _cdDurationFormat == 2
then Ceil(_cdDuration / 1440) #convert to days if greater than 1440mins
else _cdDuration; #fallback to minutes
plot calculateDuration = _calculateDuration;
}
# Entry Calculations. Note: Only parses on a Strategy Chart
def entry = round (EntryPrice(),2);
def entryPrice = if !IsNaN(entry)
then entry
else entryPrice[1];
def hasEntry = !IsNaN(entry);
def isNewEntry = entryPrice != entryPrice[1];
#is active trade
def Active = if SecondsTillTime(begin) == 0 and
SecondsFromTime(begin) == 0
then 1
else 0;
def highFPL = HighestAll(FPL);
def lowFPL = LowestAll(FPL);
def fplreturn = (FPL - FPL[1]) / FPL[1];
def cumsum = Sum(fplreturn);
def highBarNumber = CompoundValue(1, if FPL == highFPL
then bn
else highBarNumber[1], 0);
def lowBarNumber = CompoundValue(1, if FPL == lowFPL
then bn
else lowBarNumber[1], 0);
#Win/Loss ratios
def entryBarsTemp = if hasEntry
then bn
else nan;
def entryBarNum = if hasEntry and isNewEntry
then bn
else entryBarNum[1];
def isEntryBar = entryBarNum != entryBarNum[1];
def entryBarPL = if isEntryBar
then FPL
else entryBarPL[1];
def exitBarsTemp = if !hasEntry
and bn > entryBarsTemp[1]
then bn
else nan;
def exitBarNum = if !hasEntry and !IsNaN(exitBarsTemp[1])
then bn
else exitBarNum[1];
def isExitBar = exitBarNum != exitBarNum[1];
def exitBarPL = if isExitBar
then FPL
else exitBarPL[1];
def entryReturn = if isExitBar then exitBarPL - exitBarPL[1] else entryReturn[1];
def isWin = if isExitBar and entryReturn >= 0 then 1 else 0;
def isLoss = if isExitBar and entryReturn < 0 then 1 else 0;
def entryReturnWin = if isWin then entryReturn else entryReturnWin[1];
def entryReturnLoss = if isLoss then entryReturn else entryReturnLoss[1];
def entryFPLWins = if isWin then entryReturn else 0;
def entryFPLLosses = if isLoss then entryReturn else 0;
def entryFPLAll = if isLoss or isWin then entryReturn else 0;
#Counts
def entryCount = incrementValue(entryFPLAll);
def winCount = incrementValue(isWin);
def lossCount = incrementValue(isLoss);
def highestReturn = if entryReturnWin[1] > highestReturn[1]
then entryReturnWin[1]
else highestReturn[1];
def lowestReturn = if entryReturnLoss[1] < lowestReturn[1]
then entryReturnLoss[1]
else lowestReturn[1];
def winRate = round ( winCount / lossCount,2);
def winLossRatio = winCount / entryCount;
def avgReturn = TotalSum(entryFPLAll) / entryCount;
def avgWin = TotalSum(entryFPLWins) / winCount;
def avgLoss = TotalSum(entryFPLLosses) / lossCount;
#Drawdown
def lowestLowBarNumber = HighestAll(if FPL == lowFPL then bn else 0);
def highestHighBarNumber = HighestAll(if FPL == highFPL and FPL != FPL[1] then bn else 0);
def hasPrevLow = lowestLowBarNumber < highestHighBarNumber;
def isPeak = FPL > Highest(FPL[1], 12) and FPL > Highest(FPL[-12], 12);
def isTrough = FPL < Lowest(FPL[1], 12) and FPL < Lowest(FPL[-12], 12);
def _peak = if isPeak then FPL else nan;
def _trough = if isTrough then FPL else nan;
def peak = if !IsNaN(_peak) then FPL else peak[1];
def trough = if !IsNaN(_trough) then FPL else trough[1];
def peakBN = if isPeak then bn else peakBN[1];
def troughBN = if isTrough then bn else troughBN[1];
def ptvDrawdown = if !hasPrevLow then calculateDrawdown(lowFPL, highFPL) else ptvDrawdown[1];
def equityDrawdown = if isTrough and trough < peak then trough - peak else equityDrawdown[1];
def equityDrawdownPercent = if isTrough and trough < peak then calculateDrawdown(trough, peak) else equityDrawdownPercent[1];
def largestEquityDrawdown = LowestAll(equityDrawdown);
def largestEquityDrawdownPercent = LowestAll(equityDrawdownPercent);
def drawdown = if hasPrevLow
then largestEquityDrawdownPercent
else ptvDrawdown;
# Drawdown Durations
def equityDrawdownLength = if bn >= peakBN and bn <= troughBN
then troughBN - peakBN
else equityDrawdownLength[1];
def ptvDrawdownLength = if bn >= highestHighBarNumber and bn <= lowestLowBarNumber
then lowestLowBarNumber - highestHighBarNumber
else ptvDrawdownLength[1];
def equityDrawdownDuration = calculateDuration(HighestAll(equityDrawdownLength));
def equityDrawdownDurationFormat = formatDuration(HighestAll(equityDrawdownLength));
def ptvDrawdownDuration = calculateDuration(ptvDrawdownLength);
def ptvDrawdownDurationFormat = formatDuration(ptvDrawdownLength);
#Daily profit
def Midnight = if Active then FPL else Midnight[1];
def DaysProfit = Round(FPL - Midnight,2);
#Plots
AddChartBubble(!hideFPL and showEntryBubbles and isEntryBar, FPL, "Entry: " + entryBarPL + " | " + bn, Color.WHITE);
AddChartBubble(!hideFPL and showEntryBubbles and isExitBar, FPL, "Exit: " + exitBarPL,
color = if isWin
then Color.LIGHT_GREEN
else if isLoss
then Color.DARK_RED
else Color.GRAY,
up = no
);
#Labels
# test -----------------------------------------
def tmpMaxLossCount = if isLoss then tmpMaxLossCount[1] + 1 else 0;
#def maxLossCount = if tmpMaxLossCount > maxLossCount[1] then tmpMaxLossCount else MaxLossCount[1];
def maxLossCount = if iswin then 0 else if tmpMaxLossCount > maxLossCount[1] then tmpMaxLossCount else MaxLossCount[1];
AddLabel(yes,
text = "MaxLossCount " + maxLossCount,
color.ORANGE
);
# End test -------------------------------------
AddLabel(yes,
text = "LastEntry: " + AsPrice(entryPrice)
);
AddLabel(hasEntry,
text = "Current Trade % Return: " + AsPercent(cumsum),
color = if cumsum > 0
then Color.GREEN
else Color.RED
);
AddLabel(yes,
text = "Total Trades: " + entryCount,
color = Color.WHITE
);
AddLabel(yes,
text = "WinCount: " + winCount +
" | LossCount: " + lossCount +
" | WinRate: " + winRate,
color = if winRate >= targetWinRate
then Color.GREEN
else Color.RED
);
AddLabel(yes,
text = "W/L: " + AsPercent(winLossRatio),
color = if winLossRatio > targetWinLoss
then Color.GREEN
else Color.RED
);
AddLabel(yes,
text = "HighestReturn: " + AsDollars(highestReturn),
color = if highestReturn > 0
then Color.GREEN
else Color.RED
);
AddLabel(yes,
text = "LowestReturn: " + AsDollars(lowestReturn),
color = if lowestReturn > 0
then Color.GREEN
else Color.RED
);
AddLabel(yes,
text = "AvgReturn: " + AsDollars(avgReturn) +
" | AvgWin: " + AsDollars(avgWin) +
" | AvgLoss: " + AsDollars(avgLoss),
color = if avgReturn >= 0
then Color.LIGHT_GREEN
else Color.RED
);
AddLabel(yes,
text = "PeakToValley DD: " + AsPercent(drawdown) +
" | Duration: " + ptvDrawdownDuration +
if ptvDrawdownDurationFormat == 1
then " hours"
else if ptvDrawdownDurationFormat == 2
then " days"
else " mins" ,
color = if drawdown > 0
then Color.GREEN
else Color.RED
);
AddLabel(largestEquityDrawdown < 0,
text = "Largest Equity DD: " + AsDollars(largestEquityDrawdown) +
" | Duration: " + equityDrawdownDuration +
if equityDrawdownDurationFormat == 1
then " hours"
else if equityDrawdownDurationFormat == 2
then " days"
else " mins",
color = if largestEquityDrawdown > 0
then Color.GREEN
else Color.Dark_ORANGE
);
AddLabel(yes,
text = "P&L High" +
(if enableDebugging
then " at bar " + highBarNumber
else "") +
": " + AsDollars(highFPL),
color = Color.GREEN
);
AddLabel(yes,
text = "P&L Low" +
(if enableDebugging
then " at bar " + lowBarNumber
else "") +
": " + AsDollars(lowFPL),
color = Color.RED
);
AddLabel(yes,
text = "Days Profit: $" + DaysProfit,
color = if DaysProfit > 0
then Color.GREEN
else Color.RED
);
AddLabel(yes,
text = "Total Profit: " + AsDollars(FPL),
color = if FPL > 0
then Color.GREEN
else Color.RED
);
#debugging
#peaks & troughs
AddChartBubble(enableDebugging and isPeak, FPL,
text = "FPL: " + FPL
+ " | Peak: " + peak
+ " | Trough: " + trough[-1]
+ " | Drawdown: " + AsPercent(calculateDrawdown(trough, peak))
+ " | PeakBN: " + peakBN
+ " | BarNumber: " + bn,
color = Color.LIME
);
AddChartBubble(enableDebugging and isTrough, FPL,
text = "FPL: " + FPL
+ " | Peak: " + peak
+ " | Trough: " + trough
+ " | Drawdown: " + AsPercent(calculateDrawdown(trough, peak))
+ " | TroughBN: " + troughBN
+ " | BarNumber: " + bn,
color = Color.LIGHT_RED,
up = no
);
AddVerticalLine(enableDebugging and isEntryBar,
text = "EntryBarNum: " + entryBarNum
+ " | ExitBarNum: " + exitBarNum[-1]
+ " | BarNumber: " + bn,
color = Color.WHITE
);
AddVerticalLine(enableDebugging and isExitBar,
text = "EntryBarNum: " + entryBarNum[1]
+ " | ExitbarNum: " + exitBarNum
+ " | BarNumber: " + bn
+ " | EntryReturn: " + entryReturn,
color = if isWin
then Color.LIGHT_GREEN
else if isLoss
then Color.LIGHT_RED
else Color.LIGHT_GREEN
);