namespace QuantConnect
{
public class QCSP500Momentum : QCAlgorithm
{
IEnumerable<string> TickerSymbols { get; set; }
int BackTestDays { get; set; }
public override void Initialize()
{
try
{
BackTestDays = 10;
SetCash(100000);
// compute startdate and enddate.
// enddate is midnight tomorrow.
// startdate is "BackTestDays" trading days earlier.
DateTime utcNow = DateTime.UtcNow;
var baseUtcOffset = TimeSpan.FromHours(-7); // Pacific Timezone
var localNow = (utcNow + baseUtcOffset).Date;
var endDate = GetEndDate(localNow);
var startDate = GetStartDate(endDate, BackTestDays-1);
Log("Initialize. startDate:" + startDate + ", endDate:" + endDate);
SetStartDate(startDate);
SetEndDate(endDate);
TickerSymbols = GetTickerSymbols();
foreach(var tickerSymbol in TickerSymbols)
{
AddSecurity(SecurityType.Equity, tickerSymbol, Resolution.Daily);
}
}
catch(Exception ex)
{
Log("Initialize. exception:" + ex.Message);
}
}
public void OnData(TradeBars data)
{
try
{
foreach(var kvp in data)
{
var tradeBar = data[kvp.Key];
Log("OnData: key:" + kvp.Key + ", " + tradeBar.Time + ", price:" + tradeBar.Price + ", value:" + tradeBar.Value + ", high:" + tradeBar.High + ", low:" + tradeBar.Low + ", close:" + tradeBar.Close + ", period:" + tradeBar.Period);
}
}
catch(Exception ex)
{
Log("OnData. exception:" + ex.Message);
}
}
public IEnumerable<string> GetTickerSymbols()
{
var csv = "NEM";
var tickerSymbols = csv.Split(',').Select(r => r.Trim());
return tickerSymbols;
}
public DateTime GetEndDate(DateTime now)
{
var endDate = now;
while( !IsTradingDay(endDate))
{
endDate = endDate.AddDays(-1);
}
return endDate;
}
public DateTime GetStartDate(DateTime endDate, int backTestDays)
{
var date = endDate;
var startDate = date;
while (backTestDays > 0)
{
date = date.AddDays(-1);
if (IsTradingDay(date))
{
backTestDays--;
startDate = date;
Log("startDate:" + startDate + ", backTestDays:" + backTestDays);
}
}
return startDate;
}
public bool IsTradingDay(DateTime dt)
{
// exclude weekends
if ((dt.DayOfWeek != DayOfWeek.Sunday) &&
(dt.DayOfWeek != DayOfWeek.Saturday))
{
// exclude holidays
if ((dt.Date != DateTime.Parse("01/01/2015")) &&
(dt.Date != DateTime.Parse("01/19/2015")) &&
(dt.Date != DateTime.Parse("02/16/2015")) &&
(dt.Date != DateTime.Parse("04/03/2015")) &&
(dt.Date != DateTime.Parse("05/25/2015")) &&
(dt.Date != DateTime.Parse("07/03/2015")) &&
(dt.Date != DateTime.Parse("09/07/2015")) &&
(dt.Date != DateTime.Parse("11/26/2015")) &&
(dt.Date != DateTime.Parse("12/25/2015")) &&
(dt.Date != DateTime.Parse("01/01/2016")) &&
(dt.Date != DateTime.Parse("01/18/2016")) &&
(dt.Date != DateTime.Parse("02/15/2016")) &&
(dt.Date != DateTime.Parse("03/25/2016")) &&
(dt.Date != DateTime.Parse("05/30/2016")) &&
(dt.Date != DateTime.Parse("07/04/2016")) &&
(dt.Date != DateTime.Parse("09/05/2016")) &&
(dt.Date != DateTime.Parse("11/24/2016")) &&
(dt.Date != DateTime.Parse("12/26/2016")))
{
return true;
}
}
return false;
}
}
public static class Extensions
{
public static void ForEach<T>(this IEnumerable<T> seq, Action<T> fn)
{
foreach (var v in seq)
{
fn(v);
}
}
public static void ForEachIndexed<T>(this IEnumerable<T> seq, Action<T, int> fn)
{
var i = 0;
foreach (var v in seq)
{
fn(v, i);
i++;
}
}
public static void ForEachReverse<T>(this IEnumerable<T> seq, Action<T> fn)
{
foreach (var v in seq.Reverse())
{
fn(v);
}
}
public static void ForEachIndexedReverse<T>(this IEnumerable<T> seq, Action<T, int> fn)
{
var i = 0;
foreach (var v in seq.Reverse())
{
fn(v, i);
i++;
}
}
}
}