Hello, I receive this error message. Do't know how to add the data.
Failed to initialize algorithm: Initialize(): System.InvalidOperationException: Please implement GetSource(SubscriptionDataConfig, DateTime, bool) on your custom data type: CustomUniverse
Trying to implement this strategy:
Scan stocks for which the following conditions are true:
50-day SMA of SPY is above the 200-day SMA of SPY
20-day SMA of stock price is above the 50-day SMA of price
Buy when
Price has just crossed up through the eight-day SMA of the High.
Close when
Price has just crossed down through the eight-day SMA of the Low.
What is the best way to implement this strategy?
- Select stocks based on MovingAverages Crossing Overs (EMA20 > EM50)
- Buy if Close crosses ove SMA 8-day of Highs
Sell if Close crosses under SMA 8-day of Lows
Current code which causes an exception is atteched.
Help would be appreciated.
Ulrich
using System.Collections.Concurrent;
//using System.Linq;
//using QuantConnect.Data.Market;
//using QuantConnect.Data.UniverseSelection;
/*
In the Initialize() method set the fee model
AddSecurity(SecurityType.Equity."SPY");
Securities["SPY"].TransactionModel = new ConstantFeeTransActionModel(1);
*/
namespace QuantConnect
{
/*
Scan stocks for which the following conditions are true:
Price is above its 50-day average (SMA)
20-day SMA of price is above the 50-day SMA of price
50-day SMA of price is above the 200-day SMA of price
50-day average volume is greater than one million shares
Buy when
Price has just crossed up through the eight-day SMA of the High.
Close when
Price has just crossed down through the eight-day SMA of the Low.
*/
public class UW_SimpleStrategy : QCAlgorithm
{
private Symbol Universe = QuantConnect.Symbol.Create("LONG", SecurityType.Equity, Market.USA);
//Define required variables:
int quantity = 0;
decimal price = 0;
decimal tolerance = 1m; //0.1% safety margin in prices to avoid bouncing.
string symbolStr = "SPY";
DateTime sampledToday = DateTime.Now;
int number_in_Securities=0;
const decimal Tolerance = 0.01m;
bool BullMarket = false;
private SecurityChanges _changes = SecurityChanges.None;
private const decimal TargetPercent = 0.1m;
private readonly ConcurrentDictionary<Symbol, SelectionData> _averages = new ConcurrentDictionary<Symbol, SelectionData>();
private ExponentialMovingAverage ema_50;
class CustomUniverse : BaseData
{
public Symbol Symbol; // Asset symbol
public decimal Open; // Yesterday open price
public decimal High; // Yesterday high price
public decimal Low; // Yesterday low price
public decimal Price; // Yesterday close price
public decimal DollarVolume; // Traded shares x Price
public long Volume; // Traded shares
}
// class used to improve readability of the coarse selection function
private class SelectionData
//-------------------------------------------------------------------
{
public readonly ExponentialMovingAverage Fast;
public readonly ExponentialMovingAverage Slow;
public readonly SimpleMovingAverage hSMA;
public readonly SimpleMovingAverage lSMA;
public SelectionData()
{
Fast = new ExponentialMovingAverage(50);
Slow = new ExponentialMovingAverage(200);
hSMA = new SimpleMovingAverage(8); //SMA(security.Symbol, 8, Resolution.Daily, Field.High);
lSMA = new SimpleMovingAverage(8); // SMA(security.Symbol, 8, Resolution.Daily, Field.Low);
}
// computes an object score of how much large the fast is than the slow
public decimal ScaledDelta
{
get { return (Fast - Slow)/((Fast + Slow)/2m); }
}
// updates the EMA50 and EMA100 indicators, returning true when they're both ready
public bool Update(DateTime time, decimal value)
{
return Fast.Update(time, value) && Slow.Update(time, value);
}
// updates the SMA indicators, returning true when they're both ready
public bool Update_SMA(DateTime time, decimal value1, decimal value2)
{
return hSMA.Update(time, value1) && lSMA.Update(time, value2);
}
// returns uptrend or downtrend for stocks
public bool StockTrend(bool SpyTrend)
{
if (SpyTrend)
return Fast > Slow*(1 + Tolerance);
else
return Fast < Slow*(1 + Tolerance);
}
} // end of class
//Initialize the data and resolution you require for your strategy:
public override void Initialize()
{
SetStartDate(2014, 01, 01);
SetEndDate(DateTime.Now);
SetCash(25000);
// Subscriptions added via universe selection will have this resolution
UniverseSettings.Resolution = Resolution.Daily;
// Take the top 50 by dollar volume using coarse
// AddUniverse(Universe.DollarVolume.Top(50));
AddSecurity(SecurityType.Equity,"SPY",Resolution.Daily);
ema_50 = EMA("SPY", 50, Resolution.Daily);
BullMarket = ema_50 > Securities["SPY"].Close;
// if (ema_50.IsReady)
Debug ("\n+Init:" + " Ema50=" + ema_50.ToString() + " Close=" + Securities["SPY"].Close.ToString());
AddUniverse <CustomUniverse>("my-custom-universe", Resolution.Daily, data =>
{ Debug("in AddUniverse");
return from cLong in data
let bar = new TradeBar(Time, cLong.Symbol, cLong.Open, cLong.High, cLong.Low, cLong.Price,
cLong.Volume, TimeSpan.FromDays(1))//Resolution.Daily)
let selector = _averages.GetOrAdd(cLong.Symbol, sym => new SelectionData())
where cLong.Price > 10
// Update returns true when the indicators are ready,
// so don't accept until they are
where selector.Update(cLong.EndTime, cLong.Price)
where selector.Update_SMA(cLong.EndTime, cLong.High, cLong.Low)
// only pick symbols who have their 50 day ema
// over their 100 day ema
where selector.Fast > selector.Slow*(1 + Tolerance)
// Exclude SPY
where cLong.Symbol.ToString() != "SPY"
// price crossed over 8-day SMA of Low
where cLong.Price > selector.lSMA
orderby cLong.Volume descending
select cLong.Symbol;
});
} // end Initialize
//Handle TradeBar Events: a TradeBar occurs on every time-interval
public void OnData(TradeBars data) {
int i=0;
//Debug(Time.ToShortDateString() + " trace -1");
if (number_in_Securities != _changes.AddedSecurities.Count) {
Debug(Time.Date.ToShortDateString() + " Number=" + _changes.AddedSecurities.Count.ToString() );
number_in_Securities = _changes.AddedSecurities.Count;
}
//One data point per day:
// if (data.ContainsKey(symbolStr))
//if (sampledToday.Date == data[symbolStr].Time.Date) return;
//Only take one data point per day (opening price)
//price = Securities[symbolStr].Close;
// sampledToday = data[symbolStr].Time;
// Debug(Time.ToShortDateString() + " SPY Close= " + price.ToString());
// we'll simply go long each security we added to the universe
foreach (var security in _changes.AddedSecurities)
{
i++;
//SetHoldings(security.Symbol, TargetPercent);
//if (i < 30)
if (Time.Date == new DateTime(2017,10,21) )
Debug("Symbol= " + Time.ToShortDateString() + " " + security.Symbol.ToString());
if (Time.Date > new DateTime(2017,10,14) && Time.Date < new DateTime(2017,10,21))
Debug(Time.ToShortDateString() + " trace 1 " + security.Symbol.ToString());
//Get fresh cash balance: Set purchase quantity to equivalent 10% of portfolio.
decimal cash = Portfolio.Cash;
int holdings = (int)Portfolio[security.Symbol].Quantity;
//quantity = Convert.ToInt32((cash * 0.5m) / price);
quantity = 3;
if (holdings > 0 || holdings == 0) {
//If we're long, or flat: check if closed crossed under 8-day SMA Low:
// if (security.Close < (hSMA * (1-tolerance)) )
{
//Now go short: Short-EMA signals a negative turn: reverse holdings
Order(security.Symbol, -(holdings + quantity));
Log(Time.Date.ToShortDateString() + " > Go Short > Holdings: " + holdings.ToString() + " Quantity:" + quantity.ToString() + " Samples: " );
Debug(Time.Date.ToShortDateString() + " > Go Short > Holdings: " + holdings.ToString() + " Quantity:" + quantity.ToString() + " Samples: " );
}
} else if (holdings < 0 || holdings == 0) {
//If we're long, or flat: check if closed crossed over 8-day SMA High:
// if ( security.Close > (lSMA * (1+tolerance)))
{
//Now go long: Short-EMA crossed above long-EMA by sufficient margin
Order(security.Symbol, Math.Abs(holdings) + quantity);
Log(Time.Date.ToShortDateString() + "> Go Long > Holdings: " + holdings.ToString() + " Quantity:" + quantity.ToString() + " Samples: " );
Debug(Time.Date.ToShortDateString() + "> Go Long > Holdings: " + holdings.ToString() + " Quantity:" + quantity.ToString() + " Samples: " );
}
}
}
}
/// Event fired each time the we add/remove securities from the data feed
/// </summary>
/// <param name="changes">Object containing AddedSecurities and RemovedSecurities</param>
public override void OnSecuritiesChanged(SecurityChanges changes)
{
BullMarket = ema_50 > Securities["SPY"].Close;
_changes = changes;
}
//public override void OnEndOfDay() {
// if (!lSMA.IsReady) return;
// Plot("lSMA", lSMA);
// Plot("hSMA", hSMA);
//}
}
}