//This demonstrates how to code a strategy script that uses 2 profit targets. The strategy is a MACD strategy that I found on YouTube which also gives me a good opportunity to share some of my thoughts on vetting viable strategies.
// 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
// Import ZenLibrary
import ZenAndTheArtOfTrading/ZenLibrary/5 as zen
// 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)
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 -------------//
// 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=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=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
strategy.exit(id="Long Exit #1", from_entry="Long", limit=tradeTarget1, stop=tradeStop, qty_percent=i_target1)
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_percent=i_target1)
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
Position risk is calculated using a lookback swing high or low padded by an ATR multiple. The trade features a dual take-profit framework: a partial exit at a 1:1 risk-to-reward ratio with stop adjustment to breakeven, and a final exit at a 2:1 ratio. It renders directly on the main chart with inputs for EMA conditions, MACD lengths, and risk parameters.
Trend-filtered MACD crossover entries
Swing high and low stop loss with ATR buffer
Dual take-profit targets with partial exit scaling
The inputs you can change from the gear icon on the chart. Defaults are the author's.
Setting
Type
Default
Variable
EMA Filter Length
int
200
i_ema_filter
EMA Max Bars Above/Below
int
1
i_ema_filter2
Stop Loss Multiplier
float
0.5
i_stop_multi
Stop Loss Lookback
int
7
i_stop_lookback
Risk:Reward Target 1
float
1.0
i_rr1
Risk:Reward Target 2
float
2.0
i_rr2
Profit % Target 1
float
25
i_target1
Forex Risk Per Trade %
float
1.0
i_riskPerTrade
Price Source
source
close
i_price_src
Fast Length
int
12
i_fast_length
Slow Length
int
26
i_slow_length
Signal Smoothing
int
9
i_signal_length
Show all 14 settings
Setting
Type
Default
Variable
Oscillator MA Type
string
EMA
i_sma_source
Signal Line MA Type
string
EMA
i_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.
2 EMA/SMA + RSI Strategy [Alorse] combines three configurable moving averages with a short-period Relative Strength Index filter. It plots fast, slow, and trend moving averages on the price chart. Long entries trigger when the fast moving average is above the
This strategy plots on the price chart and opens long or short positions when a weighted score from MACD, Stochastic RSI, RSI, Supertrend and a moving-average crossover exceeds a user-set trigger. Each component has its own weight and candle delay. Entries can
This strategy combines Arnaud Legoux Moving Average percentage price change calculations with an adaptive Gaussian Moving Average to generate trend-following signals. Long and short entries are triggered when the ALMA change calculation crosses above or below
This strategy generates trading signals based on a selectable momentum engine, supporting MACD, RSI, Stochastic, or Rate of Change. Entries trigger on signal crosses, zero-line crosses, or threshold crosses, with an optional moving average trend filter. Risk m
255 EMA Strategy combines an exponential moving average with Average True Range bands and standard MACD crossovers to generate entry signals. Drawn directly on the price chart, it plots the central 255 EMA along with upper and lower volatility envelopes. Trade
This strategy evaluates simple moving averages and the Relative Strength Index to generate trading signals. It calculates a 10-period SMA, a 30-period SMA, and a 14-period RSI. Long positions are entered when the fast SMA crosses above the slow SMA while RSI i