Back to Community
Gold trading strategy using simple MACD with scary results

This is a very simple yet effective MACD momentum trading strategy for GDXJ (Jr. Gold Miners ETF). Apply the MACD indicator with the classic 12/26/9 setting on GDXJ at the 30-minute interval. Go long when MACD issues a buy signal and go short when MACD issues a sell signal. Take profit = +25%, stop loss = -5%. Got pretty decent results off such a basic strategy already so I was wondering what my fellow Q wizards can do to spice this thing up even more!

Shout out to Mohammed Khalfan for porting my codes to Python!

For collaboration request or general consultation, please email: [email protected] and [email protected]

Clone Algorithm
381
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Backtest ID: 598ff566d2551b50de3bd455
There was a runtime error.
20 responses

[Edited] KH pointed out that shorting can be up to 4x long value plus cash before a margin call. I had run pvr on this and arrived at a profit per dollar risked figure, and can see now that it needs a revision to trim back the max risk it was assigning to short value. A certainty is that this algo shows a profit of 494,679. One thing that might be added, and I haven't seen this anywhere yet, could be to make an effort to automatically limit shorting to its margin threshold, not easy. Some one-liners here could be useful.

Hi Seahawk, thanks for your comments but I'm not quite sure what you are referring to. The backtest above already uses Interactive Broker's commission structure and assumes basic slippage of $0.01/share. Obviously this is a very basic technical-based strategy that needs to be refined. What this algo is meant to demonstrate is the effect of momentum in GDXJ at an intraday time interval. The fact that using a basic momentum indicator like MACD works so well on GDXJ over such a long time period indicates that there is an underlying price anomaly that causes GDXJ's price to trend consistently. From knowing this, one can further create a better algo to capture this anomaly.

Personally, I've been trading GDXJ with a variant of this algo in our startup's charity fund since March along with XIV and VXX. We use 7 algos altogether and this is one of them. We allocate 15% of the account per algo per trade. Right now, we are up 12% total since inception and trading GDXJ has been the second largest contributor in performance. The trend is your friend ;)

FYI, the bottom contributors are our monthly hedge using SVXY OTM puts.

Hi Kory, I'm using Robinhood which does not allow short position, so is there alternative method instead of going short GDXJ?

@Wembo, it's no problem -- just use JDST or GDJS, which are the inverse ETFs for Junior Gold Miners.

@Kory, thanks for posting this. You're posting some great strategies. It's also great to see you've got out-of-sample actual returns to show for it -- otherwise I'd be very skeptical about over-fitting.

I made some hacks to theoretically make it Robinhood-compatible. There is a bit of a liquidity issue, since the inverse junior gold miners ETF is a bit thinly traded. This will likely be even more of an issue in live trading than as it appears in the backtest results, since orders may just not fill, and so it won't be able to switch between ETFs fast enough to be effective. I'm also not sure why the drawdown increased so heavily, but it might be because of the higher starting capital setting. Scary indeed!

Clone Algorithm
37
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Backtest ID: 5991ec258a017650daa87640
There was a runtime error.

@Viridian, Thanks! I actually build my strategies based on a proprietary framework, not just randomly data mining for the best fitted strategies. I developed a system called "PADA" (Price Anomaly Detection Algorithm) and it helps me scan all available stocks across many different time intervals to detect statistically significant price trends that it broadly classifies as Momentum, Mean-Reversion or Random Walk (no anomaly). PADA then plots each stock at each different time interval on the plot chart below (conceptual illustration only). My job then is to simply find the Momentum and/or Mean-Reversion outliers and trade them because they exhibit higher predictability/tradeability.

In this case, GDXJ at the 30-minute interval scored extremely high on the momentum scale. As a result, using momentum trading techniques like the MACD produces very good results as expected.

@Viridian, thank you for the suggestion. GDJS has little liquidation so will try to use 1/3 position of JDST since it is 3x leveraged. Let's see the result.

@Kory, you might have a hidden gem in there. Look at the following where I changed dates to have some out of sample space to analyze, and increased the initial capital.

Would remain to find more ways to spread out the trades which you have already started.

Great work!

Clone Algorithm
43
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Backtest ID: 5991e44d8a017650daa874ea
There was a runtime error.

@Kory, very interesting algo,
does your PADA detection algorithm explain why when you replace GDXJ by GDX it no longer works (40ish% with 47% DD over the same period)?
The 2 ETFs are highly correlated (over .9 on average)

I find that very odd as it would seem that even on a minute basis the 2 ETFs are also highly correlated ...

Does that mean maybe that there are opportunity to pair trade the 2 ETF on a 30 min basis for a mor eneutral strategy.... I shall look into that unless someone has a good explanation for the phenomenon?

@Guy, I used a fixed slippage model, not volume share slippage FYI.

@Viridian, liquidity for the ETF may not be an issue if the underlyings are liquid themselves. Read this:

https://am.jpmorgan.com/blob-gim/1383272223898/83456/1323416812894_Debunking-myths-about-ETF-liquidity.pdf

@Fabien, I can't spill too much of my secret sauce, but it has more to do with co-integration than correlation. For example, GDXJ and XIV are co-integrated. Below is the same algo as above but it's trading XIV instead (long only).

Clone Algorithm
381
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Backtest ID: 599210ca0f18cd4fc1c1f422
There was a runtime error.

@Kory. thanks for the link. I think they are a bit optimistic -- downplay the risks a bit! As soon as you employ limit orders on thinly traded ETFs you will find that they don't fill as easily -- and since Quantopian doesn't provide us with NAV or bid-ask spread in any of the datafeeds, we can only guess what a fair limit price is. Note also that the last executed price on a thinly traded ETF will often be WAY off from the price you'll actually be able to fill it at, as NAV and bid-ask spread maybe have moved quite a bit since last order. That creates cases where your limit order will never fill. On top of that, I think you'll find authorized participant will only provide that extra liquidity when they can make a comfortable profit on the spread between price and NAV -- and then it'll only work one way, unless you want to cross that spread again 2x. I was looking into some ETFs the other day that drift +-0.3% from NAV, which would indicate to me how incentivized the AP is to execute the arbitrage (answer: not very much until there's a 0.6% spread! That's huge, but of course the bigger the spread the more they profit).

Viridian:

I'm assuming that the increased drawdown is partially from the extra leverage/volatility of JDST vs. shorting GDXJ, and partially because I think it is easier to profit from a short a position (speaking purely hypothetical of course) than it is to buy the inverse ETF. If you only executed the short trades on Kory's strategy, the drawdown from that is about 35% . If you only executed the JDST trades in yours, the drawdown is 70%+. The GDXJ long-only trades have about 30% drawdown. Unfortunately it is one of the drawbacks for those of us who deploy via Robinhood, I've run into the same problem when trying to craft something that trades gold and can only go long.

I'll post what I've written and traded with so far once I've had the chance to clean it up a bit. It gets somewhat similar results, but either struggles or is restricted from trading during periods of lower volatility because I don't hold overnight.

@Kory interesting, I've been looking at a few strategies trading GDX/GDJ amd GLD/GDX, I'll see if we can enhance the momentum performance or use the indicator on the GDXJ leg of my pair trades...

I do have another question regarding the slippage, you've used a fixedslippage which leads to those great results but the defautl quantopian model basically divides the performance by 4 on starting notional of 100k and by 2 on 30k (still good but max DD is now 49%).

Do you have any justification/rationale for your slippage model? I cna see that the DD effect is much higher in the first years of trading but still a significant 4 to 5 points in the last 2 years (looking at yearly max dd)

@Fabien, I should have mentioned that this strategy only works for retail traders pushing small money. Most of my momentum trading strategies for intraday time intervals are not scalable at institutional level. If you try to push large million dollar orders with this algo, it would create too much slippage from its frequent trading and bleed away the alpha.

Fixed slippage is accurate below $1M IMO. Beyond that, I'd use volume share slippage

Tried to replace GDXJ with GDX, the result is totally different and much worse. Just an experiment but interesting. The coverage and performance alone for GDXJ and GDX however, are pretty similar.

@Wenbo, according to my PADA model, GDX for some reason scores low on the momentum scale, which explains why the algo does not work well with it

@Viridian Hawk I noticed the robinhood algo trades WAY more than the original. Is this because the limit orders are all not being filled at the same price? And the position is being chased to get the full position on?

@Andrew -- I have no idea. It uses the same security for the signal -- that's unmodified so the signal should be the same. There are no limit orders. Rather it's more likely the liquidity issue of the inverse ETF -- simply because Q splits up orders so that it never orders more than 2% of volume in any minute. Not sure though.