0% found this document useful (0 votes)
78 views13 pages

Hammers & Stars Strategy

This strategy trades hammer and shooting star candlestick patterns on forex pairs using the Daily timeframe according to backtesting. It uses simple filters like ATR, EMA, and date/time ranges. The script can generate alerts for the AutoView and PineConnector trading systems and includes settings for order types, position sizing, and more.

Uploaded by

Michael Bey
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
78 views13 pages

Hammers & Stars Strategy

This strategy trades hammer and shooting star candlestick patterns on forex pairs using the Daily timeframe according to backtesting. It uses simple filters like ATR, EMA, and date/time ranges. The script can generate alerts for the AutoView and PineConnector trading systems and includes settings for order types, position sizing, and more.

Uploaded by

Michael Bey
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 13

Hammers & Stars Strategy

This script trades basic hammer and shooting star candlestick patterns.

It’s an extremely simple strategy with minimal filters, and according to my personal
manual backtesting and automated trading results, performs best on the Daily chart on
certain forex pairs.

It is intended to be traded on the forex markets but theoretically should work on all
markets (especially if you optimize the settings).

The script also comes with complete AutoView automation for Oanda.

Table of Contents
How It Works
According to the default settings, the script defines a hammer candle as a candle which
closes in the upper 33% of the entire bar, and does not close equal to its open (ie. is not
a doji).

The same is true for shooting star candles – the candle must close in the lower third of
the entire bar including the top and bottom wick in order to be considered valid.

This strategy is based on the definitions provided by Investopedia, and was inspired by
a YouTube video created by my trading mentor Steven Hart.

It also includes full inbuilt automation through both AutoView and PineConnector.

If you’re unfamiliar with these services, I have an AutoView YouTube Guide and
a PineConnector YouTube Guide which you might find helpful.

These guides are designed for coders, so if you’re a coder you will find them particularly
interesting – but even if you’re not a coder, the first lesson in both series teaches you
how to set up these services.

Settings
Updated 30th July 2021:

Strategy Settings:

>= ATR Filter:


Minimum size of entry candle compared to ATR

<= ATR Filter:


Maximum size of entry candle compared to ATR

Stop Loss ATR:


Stop loss multiplier (x ATR)

R:R:
Risk:Reward profile

Fib Level:
Used to calculate upper/lower third of candle. (For example, setting it to 0.5 will mean
hammers must close >= 50% mark of the total candle size)

Start Date Filter:


Date & time to begin trading from

End Date Filter:


Date & time to stop trading
AutoView Oanda Settings:

Use AutoView:
If turned on then the script will format its alerts to be compatible with AutoView.

Use Oanda Demo:


If turned on then oandapractice broker prefix will be used for AutoView alerts (demo
account). If turned off then live account will be used

Use Limit Order:


If turned on then AutoView will use limit orders. If turned off then market orders will be
used (recommended to use limit order to mitigate spread issues)

Days To Leave Limit Order:


This is your GTD setting (good til day)

Account Balance:
Your account balance (used for calculating position size)

Account Currency:
Your account balance currency (used for calculating position size)

Risk Per Trade %:


Your risk per trade as a % of your account balance

PineConnector Settings
Use PineConnector:
If turned on then the script will format its alerts to be compatible with PineConnector.

License ID:
This is your PineConnector license ID which you can find by clicking here.

Risk Per Trade:


This is how much to risk per trade. If you’ve set PineConnector up to receive this
parameter as a percentage of your account balance, use a whole number (eg. 1 = 1%).
If you’ve set it up to be based on volume / fixed lot size then use a lot size (eg. 1 = 1
standard lot, 0.1 = mini lot etc).

MetaTrader Prefix:
This is the prefix for your MetaTrader symbols. Some brokers have a prefix before the
symbol name (eg. m-EURUSD). Only input this if your symbols have one – leave blank
otherwise.

MetaTrader Suffix:
This is the suffix for your MetaTrader symbols. Some brokers have a suffix after the
symbol name (eg. EURUSD-f). Only input this if your symbols have one – leave blank
otherwise.

Spread:
This is used to offset your limit orders if you’re using them. (Eg. 0.5 means set your buy
limit half a pip below current price).

Use Limit Order:


If turned on the script will use a limit order for trade entry, if turned off the script will use
a market order.

// Last Updated: 30th July, 2021

// @version=4

strategy("Hammers & Stars Strategy [Automated]", shorttitle="HSS", overlay=true)

// Get Strategy Settings

var g_strategy = "Strategy Settings"

stopMultiplier = input(title="Stop Loss ATR", type=input.float, defval=1.0, tooltip="Stop loss multiplier


(x ATR)", group=g_strategy)

rr = input(title="R:R", type=input.float, defval=1.0, tooltip="Risk:Reward profile",


group=g_strategy)

fibLevel = input(title="Fib Level", type=input.float, defval=0.333, tooltip="Used to calculate


upper/lower third of candle. (For example, setting it to 0.5 will mean hammers must close >= 50% mark
of the total candle size)", group=g_strategy)

// Filter Settings

var g_filters = "Filter Settings"

// ATR Filter

atrMinFilterSize = input(title=">= ATR Filter", type=input.float, defval=0.0, minval=0.0, tooltip="Minimum


size of entry candle compared to ATR", group=g_filters)

atrMaxFilterSize = input(title="<= ATR Filter", type=input.float, defval=3.0, minval=0.0,


tooltip="Maximum size of entry candle compared to ATR", group=g_filters)

// EMA Filter

emaFilterLength = input(title="EMA Filter Length", type=input.integer, defval=20, tooltip="EMA Length


for filtering trades (set to zero to disable)", group=g_filters)
emaTouchFilter = input(title="EMA Touch Filter", type=input.bool, defval=false, tooltip="Price must
touch EMA", group=g_filters)

// Date Filter

startTime = input(title="Start Date Filter", defval=timestamp("01 Jan 1000 13:30 +0000"),


type=input.time, tooltip="Date & time to begin trading from", group=g_filters)

endTime = input(title="End Date Filter", defval=timestamp("1 Jan 2099 19:30 +0000"),


type=input.time, tooltip="Date & time to stop trading", group=g_filters)

// Time Filter

timeSession = input(title="Time Session To Ignore Trades", type=input.session, defval="0600-0915",


tooltip="Time session to ignore trades", group=g_filters)

useTimeFilter = input(title="Use Time Session Filter", type=input.bool, defval=false, tooltip="Turns


on/off time session filter", group=g_filters)

// Get AutoView Settings

var g_av = "AutoView Oanda Settings"

autoview = input(title="Use AutoView?", type=input.bool, defval=false, tooltip="Turn this on to use


AutoView alerts", group=g_av)

oandaDemo = input(title="Use Oanda Demo?", type=input.bool, defval=false, tooltip="If turned on


then oandapractice broker prefix will be used for AutoView alerts (demo account). If turned off then live
account will be used", group=g_av)

limitOrder = input(title="Use Limit Order?", type=input.bool, defval=true, tooltip="If turned on then


AutoView will use limit orders. If turned off then market orders will be used", group=g_av)

gtdOrder = input(title="Days To Leave Limit Order", type=input.integer, minval=0, defval=2,


tooltip="This is your GTD setting (good til day)", group=g_av)

accountBalance = input(title="Account Balance", type=input.float, defval=1000.0, step=100,


tooltip="Your account balance (used for calculating position size)", group=g_av)

accountCurrency = input(title="Account Currency", type=input.string, defval="USD", options=["AUD",


"CAD", "CHF", "EUR", "GBP", "JPY", "NZD", "USD"], tooltip="Your account balance currency (used for
calculating position size)", group=g_av)

riskPerTrade = input(title="Risk Per Trade %", type=input.float, defval=2.0, step=0.5, tooltip="Your risk
per trade as a % of your account balance", group=g_av)

// PineConnector Settings

var g_pc = "PineConnector Settings"

pineconnector = input(title="Use PineConnector?", type=input.bool, defval=false, tooltip="Turn this on


to use PineConnector alerts", group=g_pc)
pc_id = input(title="License ID", defval="YOUR_ID", type=input.string, group=g_pc, tooltip="This is
your PineConnector license ID")

pc_risk = input(title="Risk Per Trade", defval=1, step=0.5, type=input.float, group=g_pc,


tooltip="This is how much to risk per trade (% of balance or lots)")

pc_prefix = input(title="MetaTrader Prefix", defval="", type=input.string, group=g_pc, tooltip="This is


your broker's MetaTrader symbol prefix")

pc_suffix = input(title="MetaTrader Suffix", defval="", type=input.string, group=g_pc, tooltip="This is


your broker's MetaTrader symbol suffix")

pc_spread = input(title="Spread", defval=0.5, type=input.float, group=g_pc, tooltip="Enter your


average spread for this pair (used for offsetting limit order)")

pc_limit = input(title="Use Limit Order?", defval=true, type=input.bool, group=g_pc, tooltip="If true


a limit order will be used, if false a market order will be used")

// Generate PineConnector alert string

var symbol = pc_prefix + syminfo.ticker + pc_suffix

var limit = pc_limit ? "limit" : ""

pc_entry_alert(direction, sl, tp) =>

price = pc_limit ? "price=" + tostring(pc_spread) + "," : ""

pc_id + "," + direction + limit + "," + symbol + "," + price + "sl=" + tostring(sl) + ",tp=" + tostring(tp) +
",risk=" + tostring(pc_risk)

// Get ATR

atr = atr(14)

// Check ATR Filter

atrMinFilter = high - low >= (atrMinFilterSize * atr) or atrMinFilterSize == 0.0

atrMaxFilter = high - low <= (atrMaxFilterSize * atr) or atrMaxFilterSize == 0.0

atrFilter = atrMinFilter and atrMaxFilter

// Check EMA Filter

ema = emaFilterLength == 0 ? na : ema(close, emaFilterLength)


emaLongFilter = emaFilterLength == 0 or (close > ema and not na(ema))

emaShortFilter = emaFilterLength == 0 or (close < ema and not na(ema))

emaTouchFilterLong = (low <= ema and emaTouchFilter and close[1] > ema) or not emaTouchFilter

emaTouchFilterShort = (high >= ema and emaTouchFilter and close[1] < ema) or not emaTouchFilter

// Check Date Filter

dateFilter = time >= startTime and time <= endTime

// Check Time Filter

isInSession(sess) => na(time(timeframe.period, sess)) == false

timeFilter = (useTimeFilter and not isInSession(timeSession)) or not useTimeFilter

// Merge Filters

longFilters = atrFilter and emaLongFilter and dateFilter and timeFilter and emaTouchFilterLong

shortFilters = atrFilter and emaShortFilter and dateFilter and timeFilter and emaTouchFilterShort

bgcolor(color=(useTimeFilter and isInSession(timeSession)) or not dateFilter or not atrFilter ?


color.new(color.red,70) : na, title="Filter Color")

// Calculate the 33.3% fibonacci level for current candle

bullFib = (low - high) * fibLevel + high

bearFib = (high - low) * fibLevel + low

// Determine which price source closes or opens highest/lowest

lowestBody = close < open ? close : open

highestBody = close > open ? close : open

// Determine if we have a valid setup

validHammer = lowestBody >= bullFib and close != open and not na(atr) and longFilters

validStar = highestBody <= bearFib and close != open and not na(atr) and shortFilters
// Check if we have confirmation for our setup

validLong = validHammer and strategy.position_size == 0 and barstate.isconfirmed

validShort = validStar and strategy.position_size == 0 and barstate.isconfirmed

//------------- DETERMINE POSITION SIZE -------------//

// Get account inputs

var broker = oandaDemo ? "oandapractice" : "oanda"

var tradePositionSize = 0.0

var pair = syminfo.basecurrency + "/" + syminfo.currency

// Check if our account currency is the same as the base or quote currency (for risk $ conversion
purposes)

accountSameAsCounterCurrency = accountCurrency == syminfo.currency

accountSameAsBaseCurrency = accountCurrency == syminfo.basecurrency

// Check if our account currency is neither the base or quote currency (for risk $ conversion purposes)

accountNeitherCurrency = not accountSameAsCounterCurrency and not accountSameAsBaseCurrency

// Get currency conversion rates if applicable

conversionCurrencyPair = accountSameAsCounterCurrency ? syminfo.tickerid :


accountNeitherCurrency ? accountCurrency + syminfo.currency : accountCurrency + syminfo.currency

conversionCurrencyRate = security(symbol=syminfo.type == "forex" ? conversionCurrencyPair :


"AUDUSD", resolution="D", expression=close)

// Calculate position size

getPositionSize(stopLossSizePoints) =>

riskAmount = (accountBalance * (riskPerTrade / 100)) * (accountSameAsBaseCurrency or


accountNeitherCurrency ? conversionCurrencyRate : 1.0)

riskPerPoint = (stopLossSizePoints * syminfo.pointvalue)


positionSize = syminfo.type == "forex" ? ((riskAmount / riskPerPoint) / syminfo.mintick) : 0

round(positionSize)

// Custom function to convert pips into whole numbers

toWhole(number) =>

return = atr(14) < 1.0 ? (number / syminfo.mintick) / (10 / syminfo.pointvalue) : number

return := atr(14) >= 1.0 and atr(14) < 100.0 and syminfo.currency == "JPY" ? return * 100 : return

//------------- END POSITION SIZE CODE -------------//

// Set up our GTD (good-til-date) order info

gtdTime = time + (gtdOrder * 1440 * 60 * 1000) // 86,400,000ms per day

gtdYear = year(gtdTime)

gtdMonth = month(gtdTime)

gtdDay = dayofmonth(gtdTime)

gtdString = " dt=" + tostring(gtdYear) + "-" + tostring(gtdMonth) + "-" + tostring(gtdDay)

// Calculate our stops & targets

stopSize = atr * stopMultiplier

longStopPrice = low < low[1] ? low - stopSize : low[1] - stopSize

longStopDistance = close - longStopPrice

longTargetPrice = close + (longStopDistance * rr)

shortStopPrice = high > high[1] ? high + stopSize : high[1] + stopSize

shortStopDistance = shortStopPrice - close

shortTargetPrice = close - (shortStopDistance * rr)

// Save stops & targets for the current trade

var tradeStopPrice = 0.0

var tradeTargetPrice = 0.0


// Detect valid long setups & trigger alerts

temp_positionSize = getPositionSize(toWhole(longStopDistance) * 10)

if validLong

tradeStopPrice := longStopPrice

tradeTargetPrice := longTargetPrice

tradePositionSize := temp_positionSize

// Generate PineConnector alert syntax

pc_alert = pc_entry_alert("buy", tradeStopPrice, tradeTargetPrice)

// Generate AutoView alert syntax

av_alert = "e=" + broker + " b=long"

+ " q=" + tostring(tradePositionSize)

+ " s=" + pair

+ " t=" + (limitOrder ? "limit fp=" + tostring(close) : "market")

+ " fsl=" + tostring(tradeStopPrice)

+ " ftp=" + tostring(tradeTargetPrice)

+ (gtdOrder != 0 and limitOrder ? gtdString : "")

// Send alert to webhook

alert(message=autoview ? av_alert : pineconnector ? pc_alert : "HSS Long Alert",


freq=alert.freq_once_per_bar_close)

// Detect valid short setups & trigger alerts

temp_positionSize := getPositionSize(toWhole(shortStopDistance) * 10)

if validShort

tradeStopPrice := shortStopPrice

tradeTargetPrice := shortTargetPrice

tradePositionSize := temp_positionSize

// Generate PineConnector alert syntax

pc_alert = pc_entry_alert("sell", tradeStopPrice, tradeTargetPrice)

// Generate AutoView alert syntax


av_alert = "e=" + broker + " b=short"

+ " q=" + tostring(tradePositionSize)

+ " s=" + pair

+ " t=" + (limitOrder ? "limit fp=" + tostring(close) : "market")

+ " fsl=" + tostring(tradeStopPrice)

+ " ftp=" + tostring(tradeTargetPrice)

+ (gtdOrder != 0 and limitOrder ? gtdString : "")

// Send alert to webhook

alert(message=autoview ? av_alert : pineconnector ? pc_alert : "HSS Short Alert",


freq=alert.freq_once_per_bar_close)

// Enter trades whenever a valid setup is detected

strategy.entry(id="Long", long=strategy.long, when=validLong)

strategy.entry(id="Short", long=strategy.short, when=validShort)

// Exit trades whenever our stop or target is hit

strategy.exit(id="Long Exit", from_entry="Long", limit=tradeTargetPrice, stop=tradeStopPrice,


when=strategy.position_size > 0)

strategy.exit(id="Short Exit", from_entry="Short", limit=tradeTargetPrice, stop=tradeStopPrice,


when=strategy.position_size < 0)

// Draw trade data

plot(emaFilterLength == 0 ? na : ema, color=close > ema ? color.green : color.red, title="EMA Filter")

plot(strategy.position_size != 0 or validLong or validShort ? tradeStopPrice : na, title="Trade Stop Price",


color=color.new(color.red,0), style=plot.style_linebr)

plot(strategy.position_size != 0 or validLong or validShort ? tradeTargetPrice : na, title="Trade Target


Price", color=color.new(color.green,0), style=plot.style_linebr)

//plot(strategy.position_size != 0 or validLong or validShort ? tradePositionSize : na, title="Trade Position


Size", color=color.purple, style=plot.style_linebr, transp=100)

// Draw price action setup arrows


plotshape(validLong ? 1 : na, style=shape.triangleup, location=location.belowbar, color=color.green,
title="Bullish Setup")

plotshape(validShort ? 1 : na, style=shape.triangledown, location=location.abovebar, color=color.red,


title="Bearish Setup")

You might also like