Back

Daydreaming: from 10k to 1 million (in 10 years)

A little while ago, I shared John Ehlers' MAMA and FRAMA indicators.
I decided to play a little with it, and show you the possibilities when you account for neutral fluctuations in the market.



So I present you the MAMA and FRAMA indicators, applied to AAPL over the period 2005-2015. Clearly, if you trade aggressively with all your funds on the very short term, your equity will increase the most. However, such strategies are not always replicable in real-life due to transaction costs and slippage/illiquidity issues. So just for the purpose of motivation/entertainment, here is an algorithm that turns 10k initial capital into more than 1 million in the course of 10 years. So really, this is a little (overexaggerated) demonstration to show you that you can improve your strategy if you take the cyclical behaviour of the markets into account. In order to view the resulting graph, clone the algorithm and run the backtest.

The number of trades is too high to generate a summary of the backtest, so you would need to perform backtests on individual years to judge its power statistically. In a more serious manner, if you plan on using (part) of this strategy, you should adjust the algorithm to trade less frequently. One simple way of doing so is changing the consolidation period. Right now, this is:

int _consolidated_minutes = 10

You can change this to a larger number of minutes, for example, 60 minutes, to decrease the trading frequency.

In any case, I hope you enjoy this little example.
Keep dreaming and relish your coffee ;)
Update Backtest






The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.



For completeness, here is the 60min example (with statistics!!!)
1


And here are the stats for the high frequency strategy for a shorter period (2 years)
2


Just as a little side note: if you observe the behaviour of the strategy closely, you will see that most of its losses are still due to trades in neutral periods (like all moving average-based indicators). Therefore, to improve this strategy even further, you can include some risk-aversion metric like a volatility index such as VIX.

The confirmation logic would then be as follows:

If risk-aversion is high, VIX is high. So only take short positions.
If risk-aversion is low, VIX is low. So only take long positions.

So VIX can act as a confirmation on your initial strategy. In my experience, any such confirmations are only helpful for entering a position, not for exiting. To quantify the concepts "high" and "low" in my confirmation logic above, you could do sth. like the following:

- Use a simple moving average cross-over to determine whether VIX is going up or down
- Use the MAMA&FRAMA framework again to determine direction
- Use some sort of absolute threshold (e.g. 5% or 25%)

Note how such signals work opposite of traditional signals on stocks!

This can even be extended to ratios such as VIX:VXV and such. Of course, you can also use other risk-aversion metrics to improve the directional hit rate of the algorithm.
1

More great contributions JP B, I'm always learning something reading your stuff, thanks for sharing!
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


So I noticed that there are a few typo's in your code, but when I "fixed" them it cuts the return in half. Just something interesting I thought you would want to know.

1) SmoothPeriods.Add(33*Periods[0] + .67*SmoothPeriods[0]); should be 0.33 not 33

2) in your simple risk management it calculates pps wrong when you are shorting the market, I added an if/then to check for short.

3) If your quantity you can buy is equal to or less than 0 then a new buy price will be specified but no order will be placed. I indented the _oldprice = _price; line to include it in the if statement
1


Hey Lauriston, just a head up, indenting alone is not enough to make something within an if block. Any if block with more than a single statement must use braces. So the following lines are misleading and don't do what you would expect:if (quantity > 0)
Order(_ticker, _trend_dir*quantity);
_oldprice = _price;

It should look like the following to include the oldprice=price assignment in the if block:if (quantity > 0)
{
Order(_ticker, _trend_dir*quantity);
_oldprice = _price;
}
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


@Lauriston Thank you for going over my code! Those are some nasty typos indeed. The fact that the return is cut in half is actually because of the adjusted risk management. Surprisingly enough, changing the 33 to .33 does not change much in the returns. Apparently the smoothed price isn't of much importance in the weighted moving average.

I've cloned your algorithm and adjusted the risk management as follows:

// Order logic / (simple) risk management
if (Portfolio[_ticker].IsShort == true) {
pps = ((_oldprice - _price)/_oldprice)*100;
if (pps <= -2.5M || pps >= 2.5M || _trend_dir != _old_dir) {
// End position
Liquidate(_ticker);
}
} else {
pps = ((_price - _oldprice)/_oldprice)*100;
if (pps <= -2.5M || _trend_dir != _old_dir) { // if direction is wrong
// End position
Liquidate(_ticker);
}
}


And this yields the profits from before (>1 million). So what do we learn from this? That it's smart to take profits early on short positions! Apparently shorts have the tendency to go from being profitable to being non-profitable; so liquidating when the position is in-the-money is a smart move. Just for consistency, I've also tested this with long positions but there it doesn't hold: it's more profitable to let the long positions 'run' instead of taking profits early.

So thank you again for scrutinizing my code as we have now learned that there is a profit-taking anomaly between long and short positions. Take profits early on shorts, let long positions run! :)

See my adjusted version of your code below (Sharpe of 1.45!):
0


Edit: The original backtest at the top of this page has been corrected for the typos.
So you can simply clone that one now.
0

Is there anyway to lessen the drawdown?
0

Hello guys,
First time in here and still trying to digest a lot of data and good comments you guys put together...
If someone can help with this idea... how can we buy per example, SQQQ everytime AAPL(part of this code) was supposed to be liquidated... and every time was supposed to buy AAPL as per the code, to sell the SQQQ... basically to use AAPL as the indicator but the trade the ETN SQQQ on the other direction... can someone please let me know?

So, I tried to invert the operation to sell the inverse ETN (SQQQ) when was time to buy APPL and Buy this ETN when was time to sell APPL... for some reason, I am running out of the money... doing something wrong :( ... in case someone can take a look.

0


For what its worth, I'm having the same issue on a different algorithm. Just encountered it today.

It seems that when I apply SetHoldings("SPY", 1.0m), which is a long position, it buys 1x worth of orders. However when I quickly try to go directly to a short position (SetHoldings("SPY", -1.0m), it buys -2x worth of orders (ostensibly to sell the ones I have, which is -1x, and then again to fully short it, which is another -1x).

My thinking is there's a problem calculating how much the portfolio is worth at that point in time when you are requesting to short the position. Still looking into it.

0

Welcome @Jose! @Stephen, does it rejects the order to go short? Please send me your project id to support@quantconnect.com and I'll dig into it.

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Ok so I found out that it was indeed rejecting orders to go short. I worked around this issue by doing the following when switching directly from a fully long to a fully short position (or vice versa):

What I was doing:

SetHoldings("SPY", -1.0m); // Attempt to directly take full short position from full long position (this results in many invalid orders)

What I've put in place:

SetHoldings("SPY", 0.0m); // Sell all first
SetHoldings("SPY", -1.0m); // Then take short position

In making this change, I went from having multiple invalid orders, to having every single order successfully filled. So this looks like a good workaround.

Jared, attached is a project I was knocking around if you'd like to dig around it.

0


Can't vet for how this would affect trading fees, however. The workaround I mentioned above would effectively double the trades, right?

0

Jared and Stephen,

Thanks for your input.. @jared and Stephen
I am still not understanding how to analize one stock and trade other. In order to keep it simple, I cloned your project Jared, that is checking the MA for the SPY and I tried to change to buy the SQQQ/QQQ ETN pair but the code is not trading... I think is related to the fact that, when adding these securities to the collection, they interfere on the numbers...

So just to summarize, I was looking to keep everything as it is but just buy and sell these ETNs whenever the code was doing the same for the SPY... you will see on the code.

Thanks for your help

https://www.quantconnect.com/terminal/#open/206378

0


@Jose What you are trying to do is easily done with the LEAN engine, so I think you might want to try and study the documentation for a bit to get a better understanding of how the framework handles data. For example, if you subscribe your algorithm to two tickers, it will send the data of both stocks to the OnData() event (so mixed indeed). General procedure is then to handle this data in the OnData() function. Obviously, if you have data coming in from different sources you have to account for that. You can simply ignore data from the other stock by indexing the input variable of the OnData() function. See the demos for that. Calculating the moving average (or any technical indicator) on one stock and trading another is straightforward from that point onwards :)

In any case, we are happy to help and get your strategy up and running. I'm a bit busy at the moment but I can probably take a look at your strategy next month ;)
1

I will try to understand the LEAN one... but funny or strange that nobody had needed such thing yet? To use one stock and trade other... thanks

0

@Jose, I think you just need to uncomment the lines that subscribe to QQQ and SQQQ data. In LEAN you can't trade a security that you don't have price data for.

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


JP B,

This is a really neat algo! Just for kicks, though, I applied it to a few other stocks and it didn't perform as well. I'm wondering if the indicators require some tuning per the underlying asset?

Not to sound antagonistic, but I also wonder how much of the gain we're seeing is due to buy-and-hold-Apple having stellar performance these past few years?

-Stephen

1

@Stephen

You are right, it needs to be fine-tuned to every individual underlying. Specifically, it is most profitable on stocks that exhibit cyclical behaviour. Because this strategy is purely focused on such 'predictable cycles', it will only be profitable if the underlying actually has such cycles. Cyclical behaviour often occurs when either (1) the asset is extremely popular so that there is an enormous amount of market participants or (2) when there are large institutions enforcing certain price levels. AAPL exhibits the first phenomenon. Forex is believed to have both cyclical components.

In terms of total return, this is not that important. What is more important is that the stock is extremely volatile. Why is the total return not that important? First of all, the algorithm trades on a very high frequency with a short holding period. Any cumulative total return in the long run is therefore not that important for the algorithm's total return. Second of all, the algorithm trades both ways and doesn't take 'sides' to the most profitable long term direction. Even though AAPL mainly went up over the last 10 years, the algorithm is still going short all the time. The volatility of the underlying is therefore more important. Lastly, we could say that the total return is not that important simply by comparing its absolute return to the algorithm's: a simple buy-and-hold on AAPL could've netted you a nice 840% over 10 years. The algorithm achieved closer to 11,000% total return. Mind you, that I still think this algorithm is pure for entertainment purposes, so I don't advice to trade it.

To summarise, you are completely right that AAPL's enormous increase has something to do with the success of the algorithm. But, this is not because a buy-and-hold would be profitable but because of two other reasons: (1) AAPL is a popular stock and therefore exhibits cyclical behaviour, (2) AAPL was extremely volatile so there were many opportunities to make money. The algorithm was designed to exploit such volatile movements.

Hope that answers your question :)
1

Great discussion! Thanks very much for taking the time to write that. It is VERY impressive to have pulled in 11,000% total return as opposed to 840%. And with such low deviation on top of that.

Does John Ehler discuss any techniques for calibrating the algorithm to the underlying asset? In particular, which parameters need to be calibrated?

Thanks again, and I apologize if I'm pestering you with questions. This is fascinating stuff.

0

@Stephen I've also answered your other question through the new message feature. I think you haven't noticed my reply yet, so just letting you know ;)

3

I can't upvote you enough. Thanks for answering my questions, JP :-)

0

The parameters that need to be calibrated are the _consolidated_minutes (how often you want to trade), the MAMA_FastLimit (fast moving average) and MAMA_SlowLimit (slow moving average). These moving averages are based on cycles.

One way of calibrating them is by eye:

- Take a small backtesting period
- Backtest the algorithm and click on the "MAMA" chart when done
- Zoom in to individual days and look how the moving averages fit the data
- Adjust until satisfactory

You can also take a look at my other post, in which I give a demonstration of how you can detect cycles in the price series using another of Ehlers' methods.

Good luck :)

1

Unfortunately, Ehler's moving averages though highly effective are prone to being confused.

Following Adaptive Moving Average = FAMA
MESA Adaptive moving average = MAMA
Fractal Adaptive Moving Average = FRAMA

The algorithm drawn from this paper is the MAMAFAMA.

I recently implemented the FRAMA indicator for integration into the codebase. I'm not sure how this feeds through to QC, but I guess it will be available some time or another. Is there any desire from anyone to have the MAMAFAMA algorithm pre-packaged in the same way?

0

@James Smith; Github merges are available on master within 10 minutes :) Your code is in the current code base.

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Update Backtest





0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Loading...

This discussion is closed