TICK strategy for SPY options
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © platsn

//@version=5
strategy("TICK strategy for SPY", overlay=false, pyramiding=3, initial_capital=5000, commission_type=strategy.commission.cash_per_contract, commission_value = 0.0625) 

// ******************** Trade Period **************************************
startY = input(title='Start Year', defval=2011, group = "Trading window")
startM = input.int(title='Start Month', defval=1, minval=1, maxval=12, group = "Trading window")
startD = input.int(title='Start Day', defval=1, minval=1, maxval=31, group = "Trading window")
finishY = input(title='Finish Year', defval=2050, group = "Trading window")
finishM = input.int(title='Finish Month', defval=12, minval=1, maxval=12, group = "Trading window")
finishD = input.int(title='Finish Day', defval=31, minval=1, maxval=31, group = "Trading window")
timestart = timestamp(startY, startM, startD, 00, 00)
timefinish = timestamp(finishY, finishM, finishD, 23, 59)
t1 = time(timeframe.period, "0945-1545:23456") 
window = time >= timestart and time <= timefinish and t1 ? true : false 
t2 = time(timeframe.period, "0930-1555:23456")
window2 = time >= timestart and time <= timefinish and t2 ? true : false 

trade_options = input.bool(defval=true,title="Trading Options only", group = "Trading Options")
option_amt = input.int(defval=10,title="# of options per trade", group = "Trading Options")
option_multiplier = input.float(0.007, title="Multiplier for trading options (adjust to approx. options P&L)", step=0.001, group = "Trading Options")
reinvest = input.bool(defval=false,title="Reinvest profit", group = "Trading Options")
reinvest_percent = input.float(defval=20, title = "Reinvest percentage", group="Trading Options")
daily_max = input.float(1200, title="Stop trading after Max daily profit", group="Trading Options")

// ***************************************************************************************************** Daily ATR *****************************************************
atrlen = input.int(14, minval=1, title="ATR period", group = "Daily ATR")
iPercent = input.float(5, minval=1, maxval=100, step=0.1, title="% ATR to use for SL / PT", group = "Daily ATR")
 
percentage = iPercent * 0.01
datr = request.security(syminfo.tickerid, "1D", ta.rma(ta.tr, atrlen))
datrp = datr * percentage

// plot(datr,"Daily ATR")
// plot(datrp, "Daily % ATR")

//*********************************************************** VIX volatility index ****************************************

VIX = request.security("VIX", timeframe.period, close)
vix_thres = input.float(20.0, "VIX Threshold for entry", step=0.5, group="VIX Volatility Index")

// ***************************************************** TICK Indictor *****************************************************

malen1 = input.int(5, title = "Fast EMA period", group = "TICK Indicator")
malen2 = input.int(21, title = "Slow EMA period", group = "TICK Indicator")
malen3 = input.int(21, title = "Hull MA period", group = "TICK Indicator")
malen4 = input.int(5, title = "Hull MA Smoothing", group = "TICK Indicator")

//get TICK data
// tickO = request.security("USI:TICK", timeframe.period, open)
tickC = request.security("USI:TICK", timeframe.period, close)
tickAVG = ta.ema(tickC,malen1)
tickAVG_L = ta.ema(tickC,malen2)

f_hma(_src, _length) =>
    _return = ta.wma(2 * ta.wma(_src, _length / 2) - ta.wma(_src, _length), math.round(math.sqrt(_length)))
    _return

tickHMA = f_hma(tickC, malen3)
tickHMA_MA = ta.ema(tickHMA, malen4)

tick_bull = tickAVG > tickAVG[1]
tick_bear = tickAVG < tickAVG[1]

//Plot Tick data
plot(tickC, title='TICK', color = color.new(color.white,30) , style=plot.style_line, linewidth = 1) //color = tickC > 0 ? color.green : color.red
plot(tickAVG, title='TICK 9 EMA', color = color.yellow, style=plot.style_line, linewidth = 1)
plot(tickAVG_L, title='TICK 21 EMA', color = color.new(color.red,70), style=plot.style_line, linewidth = 1)
plot(tickHMA, title='TICK 21 HMA', color = color.blue, style=plot.style_line, linewidth = 2)
plot(tickHMA_MA, title='TICK HMA Smoothed', color = color.purple, style=plot.style_line, linewidth = 2)
hline(0, color=color.white, linewidth = 1, linestyle = hline.style_solid)
hline(1000, color=color.green, linestyle=hline.style_solid, linewidth = 2)
hline(500, color=color.gray, linestyle=hline.style_dashed)
hline(-1000, color=color.red, linestyle=hline.style_solid, linewidth = 2)
hline(-500, color=color.gray, linestyle=hline.style_dashed)

// plotshape(ta.crossunder(tickHMA,tickAVG) ,"Cross down", color=color.red, style=shape.triangledown, location = location.top, size =size.tiny)
// plotshape(ta.crossover(tickHMA,tickAVG) ,"Cross up", color=color.green, style=shape.triangleup, location = location.bottom, size =size.tiny)
plotshape(ta.crossunder(tickHMA,tickHMA_MA) ,"Cross down", color=color.red, style=shape.triangledown, location = location.top, size =size.small)
plotshape(ta.crossover(tickHMA,tickHMA_MA) ,"Cross up", color=color.green, style=shape.triangleup, location = location.bottom, size =size.small)

tick_revUp = tickHMA[2] >= tickHMA[1] and tickHMA > tickHMA[1]
tick_revDown = tickHMA[2] <= tickHMA[1] and tickHMA < tickHMA[1]

plotshape(tick_revDown,"Cross down", color=color.orange, style=shape.triangledown, location = location.top, size =size.tiny)
plotshape(tick_revUp ,"Cross up", color=color.blue, style=shape.triangleup, location = location.bottom, size =size.tiny)

//Background
bgcolor(tickAVG_L > 0 ? color.green : color.red, transp=90)
bgcolor(tickC > 499 ? color.green : na, transp=70)
bgcolor(tickC < -499 ? color.red : na, transp=70)
bgcolor(tickC > 999 ? color.green : na, transp=30)
bgcolor(tickC < -999 ? color.red : na, transp=30)


lbR = input(title='Pivot Lookback Right', defval=0, group = "TICK Divergence")
lbL = input(title='Pivot Lookback Left', defval=2, group = "TICK Divergence")

rangeUpper = input(title='Max of Lookback Range', defval=60, group = "TICK Divergence")
rangeLower = input(title='Min of Lookback Range', defval=5, group = "TICK Divergence")
plotBull = input(title='Plot Bullish', defval=true, group = "TICK Divergence")
plotHiddenBull = input(title='Plot Hidden Bullish', defval=true, group = "TICK Divergence")
plotBear = input(title='Plot Bearish', defval=true, group = "TICK Divergence")
plotHiddenBear = input(title='Plot Hidden Bearish', defval=false, group = "TICK Divergence")

bearColor = color.red
bullColor = color.green
hiddenBullColor = color.new(color.green, 80)
hiddenBearColor = color.new(color.red, 80)
textColor = color.white
noneColor = color.new(color.white, 100)

plFound = na(ta.pivotlow(tickC, lbL, lbR)) ? false : true
phFound = na(ta.pivothigh(tickC, lbL, lbR)) ? false : true

_inRange(cond) =>
    bars = ta.barssince(cond == true)
    rangeLower <= bars and bars <= rangeUpper


//----------------------------------------------- TICK Divergence -------------------------------
// Regular Bullish

// Osc: Higher Low
oscHL = tickC[lbR] > ta.valuewhen(plFound, tickC[lbR], 1) and _inRange(plFound[1])

// Price: Lower Low
priceLL = low[lbR] < ta.valuewhen(plFound, low[lbR], 1)

bullCond = plotBull and priceLL and oscHL and plFound

plot(plFound ? tickC[lbR] : na, offset=-lbR, title='Regular Bullish', linewidth=2, color=bullCond ? bullColor : noneColor, transp=0)

plotshape(bullCond ? tickC[lbR] : na, offset=-lbR, title='Regular Bullish Label', text=' Bull ', style=shape.labelup, location=location.absolute, color=color.new(bullColor, 0), textcolor=color.new(textColor, 0))

//------------------------------------------------------------------------------
// Hidden Bullish

// Osc: Lower Low
oscLL = tickC[lbR] < ta.valuewhen(plFound, tickC[lbR], 1) and _inRange(plFound[1])

// Price: Higher Low
priceHL = low[lbR] > ta.valuewhen(plFound, low[lbR], 1)

hiddenBullCond = plotHiddenBull and priceHL and oscLL and plFound

plot(plFound ? tickC[lbR] : na, offset=-lbR, title='Hidden Bullish', linewidth=2, color=hiddenBullCond ? hiddenBullColor : noneColor, transp=0)

plotshape(hiddenBullCond ? tickC[lbR] : na, offset=-lbR, title='Hidden Bullish Label', text=' H Bull ', style=shape.labelup, location=location.absolute, color=color.new(bullColor, 0), textcolor=color.new(textColor, 0))


//------------------------------------------------------------------------------
// Regular Bearish

// Osc: Lower High
oscLH = tickC[lbR] < ta.valuewhen(phFound, tickC[lbR], 1) and _inRange(phFound[1])

// Price: Higher High
priceHH = high[lbR] > ta.valuewhen(phFound, high[lbR], 1)

bearCond = plotBear and priceHH and oscLH and phFound

plot(phFound ? tickC[lbR] : na, offset=-lbR, title='Regular Bearish', linewidth=2, color=bearCond ? bearColor : noneColor, transp=0)

plotshape(bearCond ? tickC[lbR] : na, offset=-lbR, title='Regular Bearish Label', text=' Bear ', style=shape.labeldown, location=location.absolute, color=color.new(bearColor, 0), textcolor=color.new(textColor, 0))

//------------------------------------------------------------------------------
// Hidden Bearish

// Osc: Higher High
oscHH = tickC[lbR] > ta.valuewhen(phFound, tickC[lbR], 1) and _inRange(phFound[1])

// Price: Lower High
priceLH = high[lbR] < ta.valuewhen(phFound, high[lbR], 1)

hiddenBearCond = plotHiddenBear and priceLH and oscHH and phFound

plot(phFound ? tickC[lbR] : na, offset=-lbR, title='Hidden Bearish', linewidth=2, color=hiddenBearCond ? hiddenBearColor : noneColor, transp=0)

plotshape(hiddenBearCond ? tickC[lbR] : na, offset=-lbR, title='Hidden Bearish Label', text=' H Bear ', style=shape.labeldown, location=location.absolute, color=color.new(bearColor, 0), textcolor=color.new(textColor, 0))


//-------------------------------------------------------- RSI ------------------------------------

src = close
rsi_len = input.int(14, minval=1, title="RSI Length", group = "RSI")
rsi_ma_len = input.int(1, minval=1, title="RSI Signal Length", group = "RSI")
rsi_up = ta.rma(math.max(ta.change(src), 0), rsi_len)
rsi_down = ta.rma(-math.min(ta.change(src), 0), rsi_len)
rsi = rsi_down == 0 ? 100 : rsi_up == 0 ? 0 : 100 - (100 / (1 + rsi_up / rsi_down))
rsi_ma = ta.sma(rsi,rsi_ma_len)

rsi_avg = math.avg(rsi,rsi_ma)

rsi_bull = rsi_avg > rsi_avg[1]
rsi_bear = rsi_avg < rsi_avg[1]

rsi_thres = input.int(20,"RSI Overbought/Oversold levels +/- from 50", group = "RSI")


//-------------------------------------------------------- Moving Average ------------------------------------

emalen1 = input.int(8, minval=1, title='Fast EMA', group= "Moving Averages")
ema1 = ta.ema(src, emalen1)



//-------------------------------------------------------------------------------------
profit = strategy.netprofit
trade_amount = math.floor(strategy.initial_capital / close) 

BSLE()=>
    strategy.opentrades > 0 ? (bar_index - strategy.opentrades.entry_bar_index(strategy.opentrades-1)) : na

min_hold = input.int(6,"Minimum bars to hold order", group = "Trading Options")

if trade_options 
    if strategy.netprofit > 0 and reinvest// and strategy.closedtrades.profit(strategy.closedtrades-1) > 0
        trade_amount := math.floor(strategy.initial_capital * option_multiplier) * (option_amt + math.floor(((profit*reinvest_percent*0.01)/strategy.initial_capital)*10))
    else
        trade_amount := math.floor(strategy.initial_capital * option_multiplier) * option_amt

// --------------------
daily_profit = 0.0

for i = 0 to strategy.closedtrades-1
    if strategy.closedtrades.exit_time(i) > time_tradingday
        daily_profit += strategy.closedtrades.profit(i)

// plot(daily_profit, "Daily P/L")

pause_trade1 = daily_profit > daily_max

trade_amount := pause_trade1 ? 1 : trade_amount

L_entry0 = ta.crossover(tickHMA, tickHMA_MA) and rsi_avg > 50  and rsi < 50 + rsi_thres and VIX > vix_thres and tickAVG > 0 //and close > ema1
S_entry0 = ta.crossunder(tickHMA,tickHMA_MA) and rsi_avg < 50  and rsi > 50 - rsi_thres and VIX > vix_thres and tickAVG < 0 //and close < ema1

L_entry1 = L_entry0 and close > ema1 
S_entry1 = S_entry0 and close < ema1

L_entry2 = strategy.opentrades == 0 and ta.barssince(L_entry0) < 2 and close > ema1
S_entry2 = strategy.opentrades == 0 and ta.barssince(S_entry0) < 2 and close < ema1


long_SL = low[1] - datrp
short_SL = high[1] + datrp

if strategy.opentrades > 0 
    long_SL := math.min(long_SL[BSLE()], low[1] - datrp)
    short_SL := math.max(short_SL[BSLE()], high[1] + datrp)


L_exit1 = tickHMA < tickHMA_MA and rsi_bear
S_exit1 = tickHMA > tickHMA_MA and rsi_bull

L_exit2 = bearCond
S_exit2 = bullCond

trade_amount_long = trade_amount
trade_amount_short = trade_amount

if (L_entry1) and window and barstate.isconfirmed //and not(pause_trade1)
    strategy.entry("Long", strategy.long, trade_amount_long)

if (S_entry1) and window and barstate.isconfirmed //and not(pause_trade1)
    strategy.entry("Short", strategy.short, trade_amount_short)
    
if L_entry2 and not(L_entry1) and window and barstate.isconfirmed //and not(pause_trade1)
    strategy.entry("Long2", strategy.long, trade_amount_long, comment="Long 2")

if (S_entry2) and not(S_entry2) and window and barstate.isconfirmed //and not(pause_trade1)
    strategy.entry("Short2", strategy.short, trade_amount_short, comment="Short 2" )

if BSLE() > min_hold and window2 and barstate.isconfirmed
    strategy.exit("Exit", "Long", stop = long_SL, comment = "Stopped out")
    strategy.exit("Exit", "Short", stop = short_SL, comment = "Stopped out")
    strategy.close("Long", when = L_exit1 or L_exit2)
    strategy.close("Short", when = S_exit1 or S_exit2)
if window2 and barstate.isconfirmed
    strategy.exit("Exit2", "Long2", stop = long_SL, comment = "Stopped out")
    strategy.exit("Exit2", "Short2", stop = short_SL, comment = "Stopped out")
    strategy.close("Long2", when = L_exit1 or L_exit2)
    strategy.close("Short2", when = S_exit1 or S_exit2)

if time(timeframe.period, "1550-1600:23456")
    strategy.close_all()
    