Strategy · Pine Script v5 · On the chart

MACD Cross Strategy

by Web3Degenerate

This strategy generates buy and sell signals on the price chart using MACD crossovers.

View on GitHub

GitHub stars2on the repository
Pine versionv5runs as is
Lines of code194
Settings15inputs
LicenceNone statedfile: MPL-2.0
Last update2 years ago13 Sep 2024

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new strategy, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart. The trades and results appear in the Strategy Tester tab; adjust the settings with the gear icon.

Source Code

194 lines of Pine Script v5 from advanced-pine-script/9.Strategy-Scripts/15.Calculating-Forex-Lot-Sizes.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

15.Calculating-Forex-Lot-Sizes.pine
//**********************************************


//Code: 
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/

//
// System Rules:
// Indicators: MACD indicator (default values), ATR (14), EMA (200)
// 1. Price must be trading above/below the 200 EMA
// 2. Only 1 bar can close above/below the 200 EMA over the past 5 bars
// 3. We take the FIRST MACD cross and ignore subsequent signals until TP/SL is hit
// 4. Stop Loss = 0.5 ATR above/below the recent swing high/low (7 bars lookback)
// 5. First take profit = 1:1 (25%)
// 6. Second take profit = 2:1 (100%)
// 7. Move stop loss to break-even after 1st target is hit
//
// @version=5
strategy("[2022] MACD Cross Strategy", overlay=true,
     currency="USD",
     calc_on_order_fills=true,
     use_bar_magnifier=true,
     initial_capital=10000,
     default_qty_type=strategy.percent_of_equity,
     default_qty_value=100, // 100% of balance invested on each trade
     commission_type=strategy.commission.cash_per_contract)
     //commission_value=0.005) // Interactive Brokers rate

// Get user input
var g_system    = "System Entry Settings"
i_ema_filter    = input.int(title="EMA Filter Length", defval=200, group=g_system)
i_ema_filter2   = input.int(title="EMA Max Bars Above/Below", defval=1, group=g_system)
i_stop_multi    = input.float(title="Stop Loss Multiplier", defval=0.5, step=0.5, group=g_system)
i_stop_lookback = input.int(title="Stop Loss Lookback", defval=7, group=g_system)
var g_risk      = "System Risk Settings"
i_rr1           = input.float(title="Risk:Reward Target 1", defval=1.0, group=g_risk)
i_rr2           = input.float(title="Risk:Reward Target 2", defval=2.0, group=g_risk)
i_target1       = input.float(title="Profit % Target 1", defval=25, group=g_risk)
i_riskPerTrade  = input.float(title="Forex Risk Per Trade %", defval=1.0)
i_useLots       = input.bool(title="Use Lots Instead Of Units", defval=false)
var g_macd      = "MACD Settings"
i_price_src     = input.source(title="Price Source", defval=close, group=g_macd)
i_fast_length   = input.int(title="Fast Length", defval=12, group=g_macd)
i_slow_length   = input.int(title="Slow Length", defval=26, group=g_macd)
i_signal_length = input.int(title="Signal Smoothing", minval=1, maxval=50, defval=9, group=g_macd)
i_sma_source    = input.string(title="Oscillator MA Type", defval="EMA", options=["SMA", "EMA"], group=g_macd)
i_sma_signal    = input.string(title="Signal Line MA Type", defval="EMA", options=["SMA", "EMA"], group=g_macd)

//------------- DETERMINE CURRENCY CONVERSION RATE ------------- { //
// Import ZenLibrary
import ZenAndTheArtOfTrading/ZenLibrary/5 as zen
// Custom function for converting units into lot sizes
unitsToLots(units) =>
    float lots = units / 100000
    lots := math.round(lots, 2)
    _return = lots * 100000
// Check if our account currency is the same as the base or quote currency or neither (for risk $ conversion purposes)
accountSameAsCounterCurrency = strategy.account_currency == syminfo.currency
accountSameAsBaseCurrency = strategy.account_currency == syminfo.basecurrency
accountNeitherCurrency = not accountSameAsCounterCurrency and not accountSameAsBaseCurrency
// Get currency conversion rates if applicable
conversionCurrencyPair = accountSameAsCounterCurrency ? syminfo.tickerid : strategy.account_currency + syminfo.currency
conversionCurrencyRate = accountSameAsBaseCurrency or accountNeitherCurrency ? request.security(conversionCurrencyPair, "D", close, ignore_invalid_symbol=true) : 1.0
// Display the current conversion currency ticker (for debug purposes)
if barstate.islastconfirmedhistory
    table t = table.new(position.top_right, 1, 2, color.black)
    table.cell(t, 0, 0, "Conversion: " + conversionCurrencyPair + " (" + str.tostring(conversionCurrencyRate) + ")", text_color=color.white, text_size=size.small)
    table.cell(t, 0, 1, "Account: $" + str.tostring(zen.truncate(strategy.equity)), text_color=color.white, text_size=size.small)
//------------- END CURRENCY CONVERSION RATE CODE ------------- }//

// Calculate MACD
[macdLine, signalLine, histLine] = ta.macd(i_price_src, i_fast_length, i_slow_length, i_signal_length)

// Get indicator values
ema = ta.ema(close, i_ema_filter)
atr = ta.atr(14)

// Check for zero-point crosses
crossUp     = ta.crossover(signalLine, macdLine)
crossDown   = ta.crossunder(signalLine, macdLine)

// Check general system filters
tradeFilters = not na(ema) and not na(atr)

// Check trend conditions
upTrend     = close > ema
downTrend   = close < ema

// Check trade conditions
longConditions  = tradeFilters and macdLine[1] < 0 and signalLine[1] < 0
shortConditions = tradeFilters and macdLine[1] > 0 and signalLine[1] > 0

// Confirm long & short setups
longSignal   = longConditions and upTrend and crossDown
shortSignal  = shortConditions and downTrend and crossUp

// Calculate stop loss
longStop    = ta.lowest(low, i_stop_lookback) - (atr * i_stop_multi)
shortStop   = ta.highest(high, i_stop_lookback) + (atr * i_stop_multi)

// Save stops & targets
var float tradeStop = na
var float tradeTarget1 = na
var float tradeTarget2 = na
var float tradeSize = na

// Count bars above/below MA
int barsAboveMA = 0
int barsBelowMA = 0

for i = 1 to 5
    if close[i] < ema[i]
        barsBelowMA += 1
    if close[i] > ema[i]
        barsAboveMA += 1

// Combine signal filters
longTrade   = longSignal  and barsBelowMA <= i_ema_filter2 and strategy.position_size == 0
shortTrade  = shortSignal and barsAboveMA <= i_ema_filter2 and strategy.position_size == 0

// Handle long trade entry (enter position, reset stops & targets)
if longTrade
    if syminfo.type == "forex"
        tradeStop := longStop
        stopDistance = close - tradeStop
        tradeTarget1 := close + (stopDistance * i_rr1)
        tradeTarget2 := close + (stopDistance * i_rr2)
        tradeSize := na
        positionSize = zen.av_getPositionSize(strategy.equity, i_riskPerTrade, zen.toWhole(stopDistance) * 10, conversionCurrencyRate)
        strategy.entry(id="Long", direction=strategy.long, qty=i_useLots ? unitsToLots(positionSize) : positionSize)
    else
        strategy.entry(id="Long", direction=strategy.long)
        tradeStop := na
        tradeTarget1 := na
        tradeTarget2 := na

// Handle short trade entry (enter position, reset stops & targets)
if shortTrade
    if syminfo.type == "forex"
        tradeStop := shortStop
        stopDistance = tradeStop - close
        tradeTarget1 := close - (stopDistance * i_rr1)
        tradeTarget2 := close - (stopDistance * i_rr2)
        tradeSize := na
        positionSize = zen.av_getPositionSize(strategy.equity, i_riskPerTrade, zen.toWhole(shortStop - close) * 10, conversionCurrencyRate)
        strategy.entry(id="Short", direction=strategy.short, qty=i_useLots ? unitsToLots(positionSize) : positionSize)
    else
        strategy.entry(id="Short", direction=strategy.short)
        tradeStop := na
        tradeTarget1 := na
        tradeTarget2 := na
    
// Handle forex trade size tracking variable
if syminfo.type == "forex" and strategy.position_size != 0 and na(tradeSize)
    tradeSize := strategy.position_size

// Handle long stops & target calculation
if strategy.position_size > 0 and na(tradeStop) and syminfo.type != "forex"
    tradeStop := longStop
    stopDistance = strategy.position_avg_price - tradeStop
    tradeTarget1 := strategy.position_avg_price + (stopDistance * i_rr1)
    tradeTarget2 := strategy.position_avg_price + (stopDistance * i_rr2)
    tradeSize := strategy.position_size

// Handle short stops & target calculation
if strategy.position_size < 0 and na(tradeStop) and syminfo.type != "forex"
    tradeStop := shortStop
    stopDistance = tradeStop - strategy.position_avg_price
    tradeTarget1 := strategy.position_avg_price - (stopDistance * i_rr1)
    tradeTarget2 := strategy.position_avg_price - (stopDistance * i_rr2)
    tradeSize := strategy.position_size

// Handle trade exits
float exitPartialUnits = math.abs(strategy.position_size / (100 / i_target1))
float exitPartialLots = unitsToLots(exitPartialUnits)
strategy.exit(id="Long Exit #1",  from_entry="Long",  limit=tradeTarget1, stop=tradeStop, qty=i_useLots ? exitPartialLots : exitPartialUnits)
strategy.exit(id="Long Exit #2",  from_entry="Long",  limit=tradeTarget2, stop=tradeStop, qty_percent=100)
strategy.exit(id="Short Exit #1", from_entry="Short", limit=tradeTarget1, stop=tradeStop, qty=i_useLots ? exitPartialLots : exitPartialUnits)
strategy.exit(id="Short Exit #2", from_entry="Short", limit=tradeTarget2, stop=tradeStop, qty_percent=100)

// Handle both long & short trade break-even stops (do this AFTER first position has exited above ^)
if strategy.position_size != tradeSize
    tradeStop := strategy.position_avg_price
    tradeTarget1 := na

// Draw conditional data
plot(ema, color=close > ema ? color.green : color.red, linewidth=2, title="EMA")
plotshape(longTrade,  style=shape.triangleup,   color=color.green, location=location.belowbar, title="Long Setup")
plotshape(shortTrade, style=shape.triangledown, color=color.red,   location=location.abovebar, title="Short Setup")

// Draw stops & targets
plot(strategy.position_size != 0 ? tradeStop : na,   color=color.red,   style=plot.style_linebr, title="Stop Loss")
plot(strategy.position_size != 0 ? tradeTarget1 : na, color=color.green, style=plot.style_linebr, title="Profit Target 1")
plot(strategy.position_size != 0 ? tradeTarget2 : na, color=color.green, style=plot.style_linebr, title="Profit Target 2")

Overview

MACD Cross Strategy applies an EMA 200 filter requiring price to trade above or below the EMA. Only the first MACD crossover is used after the filter condition is met. Stop loss is calculated as 0.5 times ATR from the recent swing high or low. Take profits use 1:1 and 2:1 risk reward ratios with the option to move stop loss to break even after the first target. Position sizing supports percent of equity or lots for forex pairs. Settings allow customization of MACD lengths, EMA filter, stop multiplier, and risk levels.

Details

Published by

Web3Degenerate on GitHub

Draws

On the price chart

Markets

Forex

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
EMA Filter Lengthint200i_ema_filter
EMA Max Bars Above/Belowint1i_ema_filter2
Stop Loss Multiplierfloat0.5i_stop_multi
Stop Loss Lookbackint7i_stop_lookback
Risk:Reward Target 1float1.0i_rr1
Risk:Reward Target 2float2.0i_rr2
Profit % Target 1float25i_target1
Forex Risk Per Trade %float1.0i_riskPerTrade
Use Lots Instead Of Unitsboolfalsei_useLots
Price Sourcesourceclosei_price_src
Fast Lengthint12i_fast_length
Slow Lengthint26i_slow_length
Show all 15 settings
SettingTypeDefaultVariable
Signal Smoothingint9i_signal_length
Oscillator MA TypestringEMAi_sma_source
Signal Line MA TypestringEMAi_sma_signal
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

106 stars

This trading strategy combines three Exponential Moving Averages (8, 14, and 50 periods by default) with Stochastic RSI and Average True Range (ATR). It enters a long position when EMA 1 is above EMA 2, EMA 2 is above EMA 3, and the Stochastic RSI %K line cros

Strategy v4 TrendOscillators & momentum
Updated 2 years ago · GPL-3.0 GitHub repository of 3 x EMA + Stochastic RSI + ATR

Momentum Rider DAILY FINAL

by greenpeas007
58 stars

This strategy combines exponential moving averages (EMA 9, 21, 50), RSI, MACD, and Supertrend indicators to enter long positions. It triggers trades using six dynamic setups based on momentum breakouts, EMA crossovers, and pullbacks. Position sizing is compute

Strategy v6 TrendOscillators & momentum Repaints
Updated 4 months ago · Custom licence GitHub repository of Momentum Rider DAILY FINAL

CombinedBinHAndClucV6

by viktors1982
36 stars

CombinedBinHAndClucV6 is a trading strategy based on the popular BinHV45 and ClucMay72018 algorithms. It calculates dual Bollinger Bands, Exponential Moving Averages, Relative Strength Index, Average True Range, and volume metrics across primary and one-hour h

Strategy v4 Volatility & bandsOscillators & momentum Repaints
Updated 2 years ago · None stated GitHub repository of CombinedBinHAndClucV6

BB Swing

by benso87
24 stars

This strategy calculates Bollinger Bands, a configurable moving average slope, Stochastic RSI, ATR, and ADX directly on the price chart. It evaluates trend bias and momentum conditions to generate long and short swing entries using percent-of-equity sizing. Th

Strategy v5 Volatility & bandsOscillators & momentum
Updated 4 years ago · MPL-2.0 GitHub repository of BB Swing

This strategy trades long and short on the price chart using a multi-timeframe TradingLatino setup. It requires EMA 10 to cross or sit above or below EMA 55 on the one-hour, four-hour, and daily charts, together with a positive ADX slope, a directional monitor

Strategy v5 TrendMoving averages
Updated 1 year ago · None stated GitHub repository of Ruckard ABCBitcoin TradingLatino A010

More Oscillators & momentum scripts

Related on ForexR

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers