MACD strategy - Free Crypto Trading Bot

MACD crypto trading bot for the Bitcoin Perpetual (BTC-PERP).

To make our community more profitable we decided to start a series in which we will review open-source TradingView strategies. The aim of the review is to select a strategy (or a number of strategies) from TradingView and run a reality check on it, optimise them and convert into alerts, so you can set it up as a bot on Wunderbit Trading platform.

Video overview

What we will provide

  • Open-strategy source

  • Strategy adjustment for particular exchange, pair and timeframe

  • Backtest

This week we decided to go with the new MACD strategy for the Bitcoin Perpetual (BTC-Perp). This strategy is based on the trend-following momentum indicator. Similarly to our RSI-VWAP version 2 we included the Money Flow index as an additional point for entry. This strategy shows a good stable profit curve and has a significant number of observations in the backtest to confirm the results.

IMPORTANT

  • Input Partial take profits in your Wunderbit Bot settings

  • This is a trend strategy and works better in the trending market

  • We added the trend identifier using the EMA and SMA interaction

  • We added inputs for the period selection, so you could see how the strategy is performing on a monthly basis.

  • ATR for Stop Loss

  • MFI was added for the additional entries.

  • Partial Take-profits

Settings

Applicable to FTX: BTC-PERP 30 min

Input

Value

Period

39

Fast Length

7

Slow Length

23

Source

close

Signal Smoothing

10

Length

15

Lower

12

Upper

80

Long Take Profit 1%

1

Long Take Profit 1 Qty

20

Trailing Stop

1.3

SL Multiplier

2

ATR Period

40

Strategy script code

You can copy this code and paste it into your TradingView

//(c) Wunderbit Trading
//@version=4
strategy("MACD Strategy", overlay=false, pyramiding=0, commission_type=strategy.commission.percent, commission_value=0.07, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, currency = currency.USD)
// FUNCTIONS
Ema(src,p) =>
ema = 0.
sf = 2/(p+1)
ema := nz(ema[1] + sf*(src - ema[1]),src)
Sma(src,p) => a = cum(src), (a - a[max(p,0)])/max(p,0)
Atr(p) =>
atr = 0.
Tr = max(high - low, max(abs(high - close[1]), abs(low - close[1])))
atr := nz(atr[1] + (Tr - atr[1])/p,Tr)
/// TREND
ribbon_period = input(39, "Period", step=1)
leadLine1 = ema(close, ribbon_period)
leadLine2 = sma(close, ribbon_period)
// p3 = plot(leadLine1, color= #53b987, title="EMA", transp = 50, linewidth = 1)
// p4 = plot(leadLine2, color= #eb4d5c, title="SMA", transp = 50, linewidth = 1)
// fill(p3, p4, transp = 60, color = leadLine1 > leadLine2 ? #53b987 : #eb4d5c)
//Upward Trend
UT=leadLine2 < leadLine1
DT=leadLine2>leadLine1
// MACD
fast_length = input(title="Fast Length", type=input.integer, defval=7)
slow_length = input(title="Slow Length", type=input.integer, defval=23)
src = input(title="Source", type=input.source, defval=close)
signal_length = input(title="Signal Smoothing", type=input.integer, minval = 1, maxval = 50, defval = 10)
sma_source = input(title="Simple MA(Oscillator)", type=input.bool, defval=false)
sma_signal = input(title="Simple MA(Signal Line)", type=input.bool, defval=false)
// Plot colors
col_grow_above = #26A69A
col_grow_below = #FFCDD2
col_fall_above = #B2DFDB
col_fall_below = #EF5350
col_macd = #0094ff
col_signal = #ff6a00
// Calculating
fast_ma = sma_source ? Sma(src, fast_length) : Ema(src, fast_length)
slow_ma = sma_source ? Sma(src, slow_length) : Ema(src, slow_length)
macd = fast_ma - slow_ma
signal = sma_signal ? Sma(macd, signal_length) : Ema(macd, signal_length)
hist = macd - signal
//plot(hist, title="Histogram", style=plot.style_columns, color=(hist>=0 ? (hist[1] < hist ? col_grow_above : col_fall_above) : (hist[1] < hist ? col_grow_below : col_fall_below) ), transp=0 )
plot(macd, title="MACD", color=col_macd, transp=0)
plot(signal, title="Signal", color=col_signal, transp=0)
/// MFI
source = hlc3
length = input(15, minval=1)
lower = input(12, minval=0, maxval=50)
upper = input(80, minval=50, maxval=100)
// DrawMFI_f=input(true, title="Draw MFI?", type=bool)
HighlightBreaches=input(true, title="Highlight Oversold/Overbought?")
// MFI
upper_s = sum(volume * (change(source) <= 0 ? 0 : source), length)
lower_s = sum(volume * (change(source) >= 0 ? 0 : source), length)
mf = rsi(upper_s, lower_s)
mfp = plot(mf, color=color.new(color.gray,0), linewidth=1)
top = hline(upper, color=color.new(color.gray, 100), linewidth=1, editable=false)
bottom = hline(lower, color=color.new(color.gray,100), linewidth=1, editable=false)
hline(0, color=color.new(color.black,100), editable=false)
hline(100, color=color.new(color.black,100), editable=false)
// Breaches
b_color = (mf > upper) ? color.new(color.red,70) : (mf < lower) ? color.new(color.green,60) : na
bgcolor(HighlightBreaches ? b_color : na)
fill(top, bottom, color=color.gray, transp=75)
// TAKE PROFIT AND STOP LOSS
long_tp1_inp = input(1, title='Long Take Profit 1 %', step=0.1)/100
long_tp1_qty = input(20, title="Long Take Profit 1 Qty", step=1)
long_trailing = input(1.3, title='Trailing Stop Long', step=0.1) / 100
long_take_level_1 = strategy.position_avg_price * (1 + long_tp1_inp)
// Stop Loss
multiplier = input(2, "SL Mutiplier", minval=1, step=0.1)
ATR_period=input(40,"ATR period", minval=1, step=1)
// Strategy
entry_long=crossover(macd,signal) or (crossover(mf,lower) and leadLine2 < leadLine1)
entry_price_long=valuewhen(entry_long,close,0)
SL_floating_long = entry_price_long - multiplier*Atr(ATR_period)
exit_long= close < SL_floating_long
///// BACKTEST PERIOD ///////
testStartYear = input(2018, "Backtest Start Year")
testStartMonth = input(1, "Backtest Start Month")
testStartDay = input(1, "Backtest Start Day")
testPeriodStart = timestamp(testStartYear, testStartMonth, testStartDay, 0, 0)
testStopYear = input(2020, "Backtest Stop Year")
testStopMonth = input(12, "Backtest Stop Month")
testStopDay = input(31, "Backtest Stop Day")
testPeriodStop = timestamp(testStopYear, testStopMonth, testStopDay, 0, 0)
testPeriod() =>
time >= testPeriodStart and time <= testPeriodStop ? true : false
if testPeriod()
if UT
strategy.entry("long", strategy.long, when=entry_long == true, comment="Insert Enter Long commnet")
strategy.exit("TP1","long", qty_percent=long_tp1_qty, limit=long_take_level_1)
strategy.exit("Trail stop","long", trail_points=entry_price_long * long_trailing / syminfo.mintick, trail_offset=entry_price_long * long_trailing / syminfo.mintick)
strategy.close("long", exit_long == true, comment="Insert exit long commnet" )

Follow this guide to automate your TradingView STRATEGY alerts. (no need for study script).