Back

Getting Build Error regarding SymbolData

Getting a build error regarding SymbolData. Trying to attach my code, hopefully it works even without the backtest results. I cloned a previous ETF rotation strategy by MichaelH to start with, and when I build it, it gets the same error as well. I am guessing this is caused by an underlying change in the platform; can anyone help me figure out this issue?
Update Backtest








namespace QuantConnect
{
/*
* QuantConnect University: Futures Example
*
* QuantConnect allows importing generic data sources! This example demonstrates importing a futures
* data from the popular open data source Quandl.
*
* QuantConnect has a special deal with Quandl giving you access to Stevens Continuous Futurs (SCF) for free.
* If you'd like to download SCF for local backtesting, you can download it through Quandl.com.
*/
public class DualMomentumSectorRotation : QCAlgorithm
{
// we'll use this to tell us when the month has ended
DateTime LastRotationTime = DateTime.MinValue;
TimeSpan RotationInterval = TimeSpan.FromDays(30);

string SPY = "SPY";
string ACWI = "ACWI";
string Tbill = "BIL";
string Bonds = "AGG";

List GEMSymbols = new List
{
SPY,
ACWI,
Tbill,
Bonds
};

// these are the growth symbols we'll rotate through
List SectorSymbols = new List
{
"XLV", //healthcare
"XLK", //technology
"XLI", //industrial
"XLU", //utilities
"XLF", //financials
"XLY", //consumerdisc
"XLP", //consumerstap
"XLB", //basic materials
"XLE", // energy
"PSR", //real estate
"IYZ" // communications
};

// we'll hold some computed data in these guys
List SymbolData = new List();

// Indicators
//Momentum _momSPY;
//Momentum _momACWI;
//Momentum _momTbill;
//DateTime sampledToday = DateTime.Now;




public override void Initialize()
{
SetStartDate(2004, 1, 1);
SetEndDate(DateTime.Now.Date.AddDays(-1));
SetCash(25000);

foreach (var symbol in GEMSymbols.Union(SectorSymbols))
{
AddSecurity(SecurityType.Equity, symbol, Resolution.Minute);
Securities[symbol].SetDataNormalizationMode(DataNormalizationMode.TotalReturn);
var momentum = MOM(symbol, 252, Resolution.Daily);

SymbolData.Add(new SymbolData
{
Symbol = symbol,
Momentum = momentum
});
}
}

private bool first = true;

//Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol.
public void OnData(TradeBars data)
{
if (first)
{
first = false;
LastRotationTime = data.Time;
return;
}

var delta = data.Time.Subract(LastRotationTime);
if (delta > RotationInterval)
{
LastRotationTime = data.Time;

var orderedMomScores = SymbolData.OrderByDescending(x => x.MomScore).ToList();
var strongSectors = orderedMomScores.Where(val => val.MomScore >= _momSPY).ToList();

foreach (var score in orderedObjScores)
{
Log(">>SCORE>>" + score.Symbol + ">>" + score.MomScore);
}

foreach (var strongSectorScore in strongSectors)
{
Log(">>SCORE>>" + strongSectorScore.Symbol + ">>" + strongSectorScore.MomScore);
}
}

if (!_momSPY.IsReady) return;

decimal holdingPercent = .5m;

if (_momSPY >= 0 && _momSPY > _momTbill)
{
Liquidate();
foreach (var etf in strongSectors)
{
SetHoldings(etf.Symbol, holdingPercent * (1m / strongSectors.count));
}
} else
{
if(Portfolio[Bonds].Quantity > 0) return;

Liquidate();
SetHoldings(Bonds, holdingPercent);
Log("Set Holdings to " + Portfolio[Bonds].Quantity + "of " + Bonds);
}
}
}
}
0

Hey Reuben, it looks like it just can't find the symbol data class; you can post this in as a new file or into the same namespace at the bottom.

class SymbolData
{
public string Symbol;

public Momentum OneMonthPerformance { get; set; }
public Momentum ThreeMonthPerformance { get; set; }

public decimal ObjectiveScore
{
get
{
// we weight the one month performance higher
decimal weight1 = 100;
decimal weight2 = 75;

return (weight1 * OneMonthPerformance + weight2 * ThreeMonthPerformance) / (weight1 + weight2);
}
}
}


The QC University algorithm "Global ETF Rotation" seems to build fine - which algorithm are you cloning with errors?
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.


Awesome stuff Reuben! I love seeing sharing and modification of algos! Interesting idea too, only invest in SPY sectors that are stronger than the aggregate of the SPY, cool stuff, I would love to see a back test when you get it running!!
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.


Jared,

Thanks. I was cloning this algo https://www.quantconnect.com/forum/discussion/comment/1127#Comment_1127, but it looks like deleted the SymbolData class from it in the process. Not sure why I saw errors; it backtested fine but still threw up errors in the console; maybe an issue from having two different projects open in different windows being edited. I think the actual error was in my project, not the one I linked to above.

To help me get familiar with the platform, is there a way to see all of the available methods and classes available? Maybe something like in-console documentation (eg, "SetHoldings -h >> [displays description, usage, available options])? I assumed SymbolData was a build-in class, still learning the in and outs of the platform (and exposing my programming inexperience int he process). I really appreciate your prompt reply.

Michael,
Thanks for the kind words. I will definitely post the results once i get the bugs worked out.
0

Oh one other question: for the Momentum indicator (and others in general), if I am using a daily Resolution, do I need to use calendar (365) or trading (~252) days for 1 year of data? I know it's a trivial question, but I haven't been able to find the appropriate documentation.
0

We did have plans for some sort of console help like that but it would just be so much work to maintain we scraped it. Honestly the best way at the moment would be to look at the base class inside the QCAlgorithm - https://github.com/QuantConnect/Lean/tree/master/Algorithm. This is divided into partial classes -- so all the indicators are in the QCAlgorithm.Indicators.cs file etc.

Rewriting the documentation is finally the highest thing on my todo list so we'll have some shiny new docs in the next week :) Its a huge job..

Re: Momentum - If I understand you correctly; currently we build daily bars from minute data, and fire the day-data-point into the momentum indicator. So you shouldn't need to do anything special to make it work with daily data -- just select your start and end periods with SetStartDate();.

If you want to do 1 data point per year for a momentum indicator, then yes you'd use 252 points for equities, 312 for FX, to build a 1 year bar.

var consolidator = ResolveConsolidator("SPY", TimeSpan.FromDays(30)); // 1 month bars
var momentum = new Momentum(12);
RegisterIndicator("SPY", momentum, consolidator, Field.Close);
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.


Based on your help above, was able to get the code to build without errors. However, now I am getting a runtime error i have not seen before, saying at least one argument has to implement Icomparable interface. Not sure where to look in my code for this error.

Also, question regarding line 139, where i refer to the count of strongSectors: I am expecting this to be 2x the number of etfs w/ momentum > spy, that the strongSectors list has a format like this: "etf1, momentumOfEtf1, etf2, momentumOfEtf2, ...". Am I interpreting this code correctly?
0


The reason you're getting that error is due to this line:var orderedMomScores = SectorSymbolData.OrderByDescending(x => x.MomScore).ToList();
And it's the runtime saying he doesn't know how to compare two instances of Momentum. Try using the following line instead:var orderedMomScores = SectorSymbolData.OrderByDescending(x => x.MomScore.Current.Value).ToList();
I've added to my to-do list to make the indicators IComparable so that they can be ordered as you expected.

This line: strongSectors = orderedMomScores.Where(val => val.MomScore >= GEMSymbolData[1].MomScore).ToList();
Will select all instances of SymbolData from the orderedMomScores list that have a momentum higher than GEMSymbolData[1].MomScore. It's not selecting the symbol and THEN the momentum score, it's selecting the instance of SymbolData that contains both of those pieces of information.

Also, I would recommend using a dictionary instead of a list so you can index them by string.Dictionary GEMSymbolData = new Dictionary();
// in initialize
GEMSymbolData.Add(symbol, new SymbolData(...));

This way you would be able to access the SPY momentum scoreby GEMSymbolData["SPY"].MomScore. The random constant integers scare me :D.

I hope this helps! Let me know if you need anything else!
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.


@MichaelH, thank you very much for your help! Really appreciate you and Jared responding so promptly. I got it to work, thought the initial results are disappointing (but that's why we backtest, right?). Digging into the trades log, it appears that the backtest engine is performing lots of small trades each month, instead of one large order to rebalance. I think that I need to implement a smarter rebalancing algo to better see what this strategy will actually do. Is there something in my code logic that is leading my backtest to behave oddly?
0


Ok found an error, had to clear the list of strongSectors at the end of each rotation cycle. Results better, essentially mimic S&P500. I set the strategy to default to SPY if no sectors exhibited greater momentum than SPY; I was surprised this occurred at all. Next, I would like to alter the strategy to hold the top (2,3,4?) sectors of the SPY, and see how that performs. May also look different lookback windows; and performance with some kind of long-short modification.
0


Looks great @Reuben! I would try and focus on detecting the periods of high volatility in 2000-2002 and 2008-2009, if you're able to move into a more stable asset (maybe cash is best during these times?) you could gain another ~40k on your ending equity result while improving your sharpe ratio!

Have a peak at this algo another user shared. It uses the CAPE ratio to detect 'bubbly' market times.
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.


@MichaelH, thanks, that really helps. Actually I had the wrong ETF set to go to in a down market; I had intended to go to Bonds during down moves. In the variety I am attaching here, I pick the top 4 sectors each month, or go to Bonds of SPY is in a downtrend. I am getting some behavior I do not understand in the 2001-2003 time frame; according to the log, the portfolio is taking a position of 0 in the safety asset, "AGG". Given that the algo is supposed to use 100% buying power (and no leverage), I don't understand why no position is taken. This happens only in the 2001-2002 time frame, not later in the 2007-2008 time frame.

Also, I am still getting a few margin calls even while setting leverage on all assets to 1x; is this supposed to happen?
0


Hey @Reuben!

We're getting ready to deploy a fix for the leverage=1 margin calls. First we need to wait for some backtests to stop so we don't kill user's jobs :) I'll try and take a peak at your code later tonight and see if I can figure out the 0 position in AGG.
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.


Hey Reuben, I'd recommend checking data with the "Data Manager" tab -- The AGG share started on 2003-09-26 :)
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