Back

Composable Indicators

I don't know about you guys but I love charts! And what good is a chart without indicators, right? So naturally, when I ventured into this glorious universe we call QuantConnect, the first thing I wanted to do is get some squiggles up on the screen.

What I've done here is try to package up a core design philosophy I have about indicators (really they're sequential forward-only filters, but that's a mouthful!). The idea is that a filter works on a stream of data. More importantly, the filter doesn't care where the data came from... just that it's new data and needs to be accounted for in the filter's state. Looking at a filter like this it immediately lends itself to a recursive relationship, where a filter's input can be the output from another filter! This has many application in quantitative finance for the technical traders. What exactly is a 'signal line' other than an indicator on top of another indicator. Think back to the classic MACD cross. The 'fast' line is the actual MACD (difference between two moving averages) and the signal line is typically a 9 day SMA of the MACD, and when they cross it means something special. Baking this concept into the IIndicator infrastructure is central to achieving composability.

So I took a little time and whipped up some of the basic indicators. We now have easy access to SMA, EMA, RSI, and MACD. We also have access to what I've called the 'WrappedIndicator' which is defining an indicator from two existing ones by 'piping data' from the 'root' indicator to the 'wrapper' indicator. Moreover, adding new indicators should be easy as pie with two abstract classes to lend you much of the implementation. See the IndicatorBase and the WindowIndicator abstract classes. IndicatorBase is just that, it's a base and can be used by all indictors as it enforces the IIndicator contract invariants. WindowIndicator using a RollingWindow (very similar to FixedSizeQueue I've seen elsewhere, with the added benefit of this[int] accessors being well defined). I've also included some static functions in the algorithm class itself to allow for easy instantiation of these types. After placing the static functions in your algorithm class (along with supporting classes... there are many!) you can write code like this:


public override void Initialize()
{
// initialize your indicators in the Initialize method

sma = SMA(14); // create a SimpleMovingAverage of period 14
ema = EMA(14); // create an ExponentialMovingAverage of period 14
macd = MACD(14, 26); // create a MovingAverageConvergenceDivergence with fast=14 and slow=26, defaults to MovingAverageType.Simple
rsi = RSI(14); // create a RelativeStrengthIndex of period 14

// now say we actually want to get the MACD of the RSI(14)... we can easily do that!!
// this 'Of' method is an extension method defined on IndicatorExtensions and makes for better code readability
// under the hood all it does is create a new WrappedIndicator which pipes the data through the 'root' indicator and then
// pipes the 'root' indicator's output to the 'wrapper' inidicator
macdOfRsi = macd.Of(rsi);
}

public override void OnTradeBar(Dictionary data)
{
// update your indicators when you get new data for the indicator... if it's a daily indicator make sure you only feed it data daily!
TradeBar bar;
if (data.TryGetValue("SPY", out bar)
{
var dataPoint = DataPoint.Create(bar.Time, bar.Close);
sma.Update(dataPoint);
ema.Update(dataPoint);

// an important not here is that calling Update will also call update on the child
// indicators, in this case, rsi and macd from the Initialize method
macdOfRsi.Update(dataPoint);
}
}


Sadly, there's a fair amount of files here, but I think they're worth a serious look for anyone developing strategies involving indicators. Hopefully in the future we'll get an update that gives QuantConnect better web support for many files -- hint hint Jared -- folders!! :D.

Phew, I think that's enough for now (its almost 2am!). Also, please excuse me, I didn't write complete unit tests so if there's a bug please let me know.

As always, feedback is appreciated!
Update Backtest








Wow Michael very cool! Can you please attach the project and I'll dig into the underlying code. If OK we'll shuffle most of this into the QCAlgorithm base class - it will soon be open sourced with the LEAN engine and we can start building them into a long term / organized structure. If its in the underlying QCAlgorithm/Common folder it will be automatically available in all QC algorithms in the future :)
1

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.


It seems last night I was unable to attach any projects. I swear I attached the project here. I'm doing it now.

EDIT: Unable to attach the project -- console doesn't show any errors -- the call to /editcomment goes through and I even get a response... me=confused. Must be something server side.
1


Sorry about that, other people see the project :) It just doesn't update the post-view immediately after submitting, hit refresh on the page and it will redraw the discussion forum. I'll put the JS inject code there shortly.
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.


No worries, I now too see the project attached. I wonder if there is a time delay, because I suspected something like that to be the case but was unable to get it to show when I opened a new tab... I see it clearly now, thanks!!

In other news, it looks like I have enough files in there that the 'code' drop down doesn't fit! +1 for first world problems :)
0

Just had a chance to go through these thoroughly, they're *beautifully* designed! Nice work!

I especially like the static wrappers on new instances to give the X = SMA(10); user interface. If we made a static Indicator global class perhaps we can make the indicator base automatically subscribe itself for needing updates - then the QCAlgorithm pushes updates to Indicator global class and it distributes them to everything subscribed
1

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.


Thanks! And I've been thinking about the auto subscribe indicators. I might have some time today to throw something together. I do like the static indicator functions as well, it makes for easier reading/coding, especially folks newer to QuantConnect.

The only concern I have with having the base type do this is the extra information required. Are we grabbing data from a TradeBar? If so, which property? Can it be computed? What if it's a custom data source? Which 'column' of the custom data are we trying to filter. Instead, I was thinking we would have something like an IndicatorManager type would could live on QCAlgorithm. Those static functions could become instance functions and could have a signature something like this


public SimpleMovingAverage SMA(
string symbol,
int period,
// we would have another for tick that would accept (and a final one for T)
// Func selector =
Func selector = null // we can default to Close
)
{
string name = symbol + "SMA" + period;
var sma = new SimpleMovingAverage(name, period);

// this guy doesn't exist yet, but he could live on QCAlgorithm
// and basically be a lookup (by symbol, by name) of indicators
IndicatorManager indicators = this.Indicators;

// default to close
selector = selector ?? (x => x.Close);

// the IndictorManager could hold the data required to map OnData( ... )
// method data to each indicator
indicators.AddTradeBarIndicator(symbol, sma, selector);

return sma;
}
0

Compiling this project gives a bunch of errors :)
0

They are basically all in the base class now Tadas :) I'll close thread and disable algorithm later today since it conflicts with base classes
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.


Understood.
0

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