Professional Documents
Culture Documents
0 at
https://mozilla.org/MPL/2.0/
// 2020 © io72signals / Antorio Bergasdito
//@version=4
strategy("72s Strategy: Adaptive Hull Moving Average+ pt.1", shorttitle="72s Strat:
Adaptive HMA+ pt.1", overlay=true,
pyramiding=1, initial_capital=1000,
commission_type=strategy.commission.cash_per_order, commission_value=.5,
slippage=3, max_bars_back=1000)
atrBase = atr(21)
src = close
adaptPct = 0.03141
//{ INPUTS
orderSize = input(0.1, title="Order Size (in Lot)", step=.1, group="ORDERS")
minProfit = input(1, step=.1, title="Base Minimum Profit before exit (ATR)",
group="ORDERS") * atrBase
takeProfit = input(3, step=.1, title="Default Target Profit (ATR)",
group="ORDERS") * atrBase
useSL = input(true, title="Use StopLoss", group="ORDERS")
SLInput = input("Half Distance Zone", title="Base StopLoss Point",
options=["One Distance Zone", "Half Distance Zone", "Last
High/Low", "ATR Only"], group="ORDERS")
maxSL = input(4.5, step=.1, title="Maximum StopLoss (ATR)", group="ORDERS") *
atrBase
//Dynamics
var float dynamicLength = avg(minLength,maxLength)
var float minorLength = avg(minorMin,minorMax)
dynamicLength := iff(charged, max(minLength, dynamicLength * (1 - adaptPct)),
min(maxLength, dynamicLength * (1 + adaptPct)))
minorLength := iff(charged, max(minorMin, minorLength * (1 - adaptPct)),
min(minorMax, minorLength * (1 + adaptPct)))
//Adaptive HMA
xhma(_src,_length) => _return = wma(2 * wma(_src, _length / 2) - wma(_src,
_length), floor(sqrt(_length)))
_slope = calcslope(dynamicHMA)
plotchar(_slope, "slope is:", "", location.top) //<--Output current slope to Data
Window, for our reference when optimizing Strategy
//Envelope the main DynamicHMA with ATR band, just one way to approximate current
price distance to MA. Other usages/methods may vary.
upperTL = dynamicHMA + mult * atr(40) , lowerTL = dynamicHMA - mult *
atr(40) //<--Half distance zone
topTL = dynamicHMA + (mult*2) * atr(40) , botTL = dynamicHMA - (mult*2) *
atr(40) //<--One distance zone
stopupperTL = dynamicHMA + (mult/2) * atr(40), stoplowerTL = dynamicHMA - (mult/2)
* atr(40) //<--Half of the half. If need ie. tighter SL or trailing
//EMA 200. (Not being use in here. But since they've been a BFF since long, thought
I'm just gonna put it here..)
emma200 = ema(close,200) //, plot(emma200)
//}...adaptive HMA+
//{ SIGNALS
//Base; When HMA+ turn to a darker color and market is out from low volatility
upSig = _slope >= flat and charged
dnSig = _slope <= -flat and charged
//Default buy/sell, when market switchs to the above base condition, and typical
price is still in tolerated distance, and RSI is on the right side.
buy = upSig and not upSig[1] and close>dynamicHMA and low<=upperTL and (rsi>51
and rsi<=70)
sell = dnSig and not dnSig[1] and close<dynamicHMA and high>=lowerTL and (rsi<49
and rsi>=30)
//Alternative buy/sell, when price is a bit far from MA, and RSI is still on the
same side but already on oversold/overbought (relatively).
overBuy = upSig and not upSig[1] and rsi>70 and close>dynamicHMA and hl2>upperTL
and minorHMA>dynamicHMA
overSell= dnSig and not dnSig[1] and rsi<30 and close<dynamicHMA and hl2<lowerTL
and minorHMA<dynamicHMA
//Plot 'em up
atrPos = 0.2 * atr(5)
plotshape(buy? dynamicHMA-atrPos:na,color=color.green, location=location.absolute,
style=shape.labelup, text="buy", textcolor=color.white, size = size.small)
plotshape(sell? dynamicHMA+atrPos:na, color=color.red, location=location.absolute,
style=shape.labeldown, text="sell", textcolor=color.white, size = size.small)
plotshape(overBuy? dynamicHMA-atrPos:na,color=color.green,
location=location.absolute, style=shape.labelup, text="overBuy",
textcolor=color.white, size = size.small)
plotshape(overSell?dynamicHMA+atrPos:na, color=color.red,
location=location.absolute, style=shape.labeldown, text="overSell",
textcolor=color.white, size = size.small)
//Alert
if buy
alert("Buy signal at "+tostring(close), alert.freq_once_per_bar_close)
if sell
alert("Sell signal at "+tostring(close), alert.freq_once_per_bar_close)
if overBuy
alert("OverBuy signal at "+tostring(close), alert.freq_once_per_bar_close)
if overSell
alert("OverSell signal at "+tostring(close), alert.freq_once_per_bar_close)
if doubleUp and secondBuy
alert("2nd Buy signal at "+tostring(close), alert.freq_once_per_bar_close)
if doubleUp and secondSell
alert("2nd Sell signal at "+tostring(close), alert.freq_once_per_bar_close)
//}...signals
//{ ORDERS
//(I use Lot just because it's how I usually trade, matches my flow when
thinking/planning. Change the "qty" in "strategy.entry()" below to use other UOM.)
//Forex pairs are 100,000 units per 1 lot. Units per 1 lot vary on non-forex pairs,
please check with your broker and change accordingly if necessary.
//(ie: In MT4 and MT5 right click a symbol and then click Specification. The
Contract Size field tells how many units are in one lot.)
standard1LotUnits =
syminfo.type == "forex" ? 100000 :
syminfo.ticker == "XAUUSD" ? 100 :
syminfo.ticker == "XAGUSD" ? 5000 :
syminfo.type == "crypto" ? 1 : 1000
//{ StopLoss
SLHighMax = high + maxSL, SLLowMax = low - maxSL //<--Maximum StopLoss. If a
chosen SL-point from input above happen
// to be outside this max
point, then this one will be use as SL.
//This part will also make your TP/SL change dynamically if there's a new signal
while you have an open position.
//If you want to fire this TP/SL only in a new position, then add
"strategy.position_size == 0"
if (buy or sell or overBuy or overSell) //and strategy.position_size == 0
entryPrice := close
if buy or sell and strategy.position_size == 0
normOrder := 1
if overBuy or overSell and strategy.position_size == 0
riskOrder := 1
buyTP := high + takeProfit
sellTP := low - takeProfit
if buy or overBuy
buySL := SLLowMax<SLBuy? SLBuy:SLLowMax
if sell or overSell
sellSL:= SLHighMax>SLSell? SLSell:SLHighMax
//Exit Conditions
exitBuy = ( close >= minBuyProfit and (RSIexitBuy or
crossunder(close,dynamicHMA)) ) or stopLossBuy or takeProfitBuy
exitSell = ( close <= minSellProfit and (RSIexitSell or crossover(close,dynamicHMA)
) ) or stopLossSell or takeProfitSell
exitoverBuy = ( close >= minBuyProfit and (crossunder(rsi,45) or
(open<stopupperTL and hl2<stopupperTL)) ) or (open<dynamicHMA and rsi<60)
or stopLossBuy or takeProfitBuy
exitoverSell = ( close <= minSellProfit and (crossover(rsi,55) or
(open>stoplowerTL and hl2>stoplowerTL)) ) or (open>dynamicHMA and rsi>40)
or stopLossSell or takeProfitSell
if inBuyExit or inSellExit
if normOrder == 1 and exitBuy
normOrder := 0, alert("Close Buy Position/s at "+tostring(close),
alert.freq_once_per_bar_close)
if normOrder == 1 and exitSell
normOrder := 0, alert("Close Sell Position/s at "+tostring(close),
alert.freq_once_per_bar_close)
if riskOrder == 1 and exitoverBuy
riskOrder := 0, alert("Close overBuy Position/s at "+tostring(close),
alert.freq_once_per_bar_close)
if riskOrder == 1 and exitoverSell
riskOrder := 0, alert("Close overSell Position/s at "+tostring(close),
alert.freq_once_per_bar_close)
if in2ndBuyExit
alert("Close 2nd Buy Position/s at "+tostring(close),
alert.freq_once_per_bar_close)
if in2ndSellExit
alert("Close 2nd Sell Position/s at "+tostring(close),
alert.freq_once_per_bar_close)
//{ Actions
//ENTRIES
strategy.entry("buy", strategy.long, qty=lotSize, when=buy )
strategy.entry("sell", strategy.short, qty=lotSize, when=sell)
strategy.entry("overBuy", strategy.long, qty=lotSize, when=overBuy )
strategy.entry("overSell", strategy.short, qty=lotSize, when=overSell)
if doubleUp
strategy.entry("2ndBuy", strategy.long, qty=lotSize, when=secondBuy )
strategy.entry("2ndSell", strategy.short, qty=lotSize, when=secondSell)
//EXITS
//We use just "strategy.close" because we already set limit conditions above for SL
and TP, fires at candle close. If you want to
//separate exit data or exit at the exact SL/TP you can add such as:
strategy.exit("exitbuy", from_entry="buy", stop=buySL, limit=buyTP)
//accordingly. And delete stopLossBuy, stopLossSell, takeProfitBuy, takeProfitSell
definitions from above.
strategy.close("buy", when=exitBuy , comment="close buy")
strategy.close("sell", when=exitSell, comment="close sell")
strategy.close("overBuy", when=exitoverBuy , comment="close overBuy")
strategy.close("overSell", when=exitoverSell, comment="close overSell")
if doubleUp
strategy.close("2ndBuy", when=exitSecondBuy , comment="close 2nd Buy")
strategy.close("2ndSell", when=exitSecondSell, comment="close 2nd Sell")
//}---actions
//{------------------------------------------------------------------------
//Below is just fancy stuff approximating gain in pips. You probably don't need
this.
//(Also I'm not too sure this is the right way calculating pip gain in pine. If
somebody knows how, kindly correct me please)
mUnit = lotSize*pip()
ppip = round((strategy.grossprofit-strategy.grossprofit[1]) /
syminfo.pointvalue/mUnit,1)
lpip = round((strategy.grossloss-strategy.grossloss[1]) /
syminfo.pointvalue/mUnit,1)
pipGain = round((strategy.grossprofit/syminfo.pointvalue)/mUnit)
pipLoss = round((strategy.grossloss/syminfo.pointvalue)/mUnit)
avg_ppip = round((pipGain/strategy.wintrades),1)
pctProfit = round(strategy.wintrades/strategy.closedtrades * 100, 2)
maxDD = ceil(strategy.max_drawdown/ syminfo.pointvalue/mUnit) //check if our margin
can handle DD's pips*orderSize
var txt2 = ""
txt = "Total trades: "+ tostring(strategy.closedtrades)+"\n("+tostring(pctProfit)
+"%) Win: "+tostring(strategy.wintrades)+" / Loss: "+tostring(strategy.losstrades)+
"\nAverage win pips per trade: "+ tostring(avg_ppip) + " pips\n\nApproximate
(*give n take)\nTotal Pip Gain: "+ tostring(pipGain) +" pips"+
"\nTotal Pip Loss: "+tostring(pipLoss)+ " pips"+"\n\nMax Drawdown so far:
"+tostring(maxDD)+" pips"
if strategy.wintrades>strategy.wintrades[1]
txt2 := "\n\nLast closed trade: Bagged "+tostring(ppip)+" pips 👻"
if strategy.losstrades>strategy.losstrades[1]
txt2 := "\n\nLast closed trade: Blew "+tostring(lpip)+" pips 😪"
txt += txt2
label pvtLabel = label.new(time, lowestLow, text=txt,
color=color.new(color.white,100), xloc=xloc.bar_time,
style=label.style_label_left, textcolor=color.gray, textalign=text.align_left)
label.set_x(pvtLabel, label.get_x(pvtLabel) + ((time-time[1]) * 21))
label.delete(pvtLabel[1])
//}