STR:EMA Oscilator [Azzrael]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Azzrael

// Based on EMA and EMA Oscilator https://www.tradingview.com/script/qM9wm0PW-EMA-Oscilator-Azzrael/

// (EMA - close) + Std Dev + Factor = detecting oversell/overbuy
// Long only!
// Pyramiding - sometimes, depends on ...
// There 2 enter strategies in one script 
// 1 - Classic, buy on entering to OverSell zone (more profitable ~> 70%)
// 2 - Crazy, buy on entering to OverBuy zone (catching trend and pyramiding, more net profit)
// Exit - crossing zero of (EMA - close)

//@version=5
strategy("STR:EMA Oscilator [Azzrael]", overlay=false, 
 initial_capital=1000,
 default_qty_type=strategy.percent_of_equity,
 default_qty_value=30,
 pyramiding=3,
 commission_type=strategy.commission.percent,
 commission_value=0.1
 )

ema_length = input.int(200, "Period", minval=2, step=10)
limit = input.float(1.7, "Factor", minval=1, step=0.1, maxval=10)
dno = input.string(defval="Buy on enter to OverSell", title="Model", options=["Buy on enter to OverSell", "Buy on enter to OverBuy"]) == "Buy on enter to OverSell"

dt_start = input.time(defval=timestamp('01 January 2001 00:00 +0000'), title='Start', group ="Backtest period")
dt_end = input.time(defval=timestamp('01 January 2030 00:00 +0000'), title='Finish', group ="Backtest period")
bar_in_period = time >= dt_start and time <= dt_end

v = close - ta.ema(close, ema_length)
dev = ta.stdev(v, ema_length)
k = dno ? -1 : 1
dev_limit = k*dev*limit

cond_long = barstate.isconfirmed and bar_in_period and (dno ? ta.crossunder(v, dev_limit) : ta.crossover(v, dev_limit))
cond_close = barstate.isconfirmed and bar_in_period and ta.cross(v, 0) 

// dev visualization
sig_col = (dno and v <= dev_limit) or (not dno and v >= dev_limit) ? color.green : color.new(color.blue, 80)
plot(dev_limit, color=color.green)
plot(k*dev, color=color.new(color.blue, 60))
plot(v, color=sig_col )
hline(0)

// Make love not war
if cond_long
    entry_name="b" + str.tostring(strategy.opentrades)
    strategy.entry(entry_name, strategy.long)

if cond_close and strategy.position_size > 0
    strategy.close_all("s")

if time >= dt_end or barstate.islastconfirmedhistory
    strategy.close_all("last")
