| Overall Statistics |
|
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio 0 Tracking Error 0 Treynor Ratio 0 Total Fees $0.00 |
using QuantConnect.Data.Market;
using QuantConnect.Indicators;
using System;
using System.Collections.Generic;
using System.Linq;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// First full-fledged attempt at the ENF data backtesting
/// </summary>
public class ENF1 : QCAlgorithm
{
const string liveDataDownloadUrl = "...tbd...";
const string backtesFDataDownloadUrl = "...tbd...";
private DateTime lastOnDataTime = DateTime.MinValue;
/// <summary>
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
/// </summary>
public override void Initialize()
{
// Load the IKF Data Manager
var url = LiveMode ? liveDataDownloadUrl : liveDataDownloadUrl;
int records = ENFDataManager.LoadData(url);
Debug("ENFDataManager loaded " + records + " records.");
// Set Start and End dates for backtesting -- use our ENFDataManager data range
SetStartDate(2016,11,1);
SetEndDate(2016,11,18);
// Set cash for backtesting purposes
SetCash(100000);
// TODO: !!! ??Is this really necessary?? !!!
// Find more symbols here: http://quantconnect.com/data
AddSecurity(SecurityType.Equity, "SPY", Resolution.Hour);
UniverseSettings.Resolution = Resolution.Second;
AddUniverse(new PreMarketDailyUsEquityUniverse(UniverseSettings, SecurityInitializer, TimeSpan.FromMinutes(60), dateTime =>
{
// If we're LiveMode, then we need to reload the data each day
if (LiveMode)
{
ENFDataManager.LoadData(url);
}
// Return the list of symbols
var symbols = ENFDataManager.SymbolList(dateTime);
Debug("Universe selection trigger time: " + dateTime + " - Number of symbols: " + symbols.Count());
return symbols;
}));
}
/// <summary>
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
/// </summary>
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
public void OnData(TradeBars data)
{
if (lastOnDataTime.Date != data.Time.Date)
{
// a new day!
Debug("OnData: Date: " + data.Time.Date + " - Count: " + data.Count);
}
lastOnDataTime = data.Time;
}
}
}/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Clone of: CustomUniverseTriggerTimesAlgorithm
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using QuantConnect.Data;
using QuantConnect.Data.Market;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Indicators;
using QuantConnect.Securities;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Specifies a universe which fires before us-equity market open each day
/// </summary>
public class PreMarketDailyUsEquityUniverse : UserDefinedUniverse
{
private readonly TimeSpan _timeBeforeMarketOpen;
public PreMarketDailyUsEquityUniverse(UniverseSettings universeSettings, ISecurityInitializer securityInitializer, TimeSpan timeBeforeMarketOpen, Func<DateTime, IEnumerable<string>> selector)
: base(CreateConfiguration(), universeSettings, securityInitializer, TimeSpan.MaxValue, selector)
{
_timeBeforeMarketOpen = timeBeforeMarketOpen;
}
// this configuration is used internally, so we'll create a us-equity configuration
private static SubscriptionDataConfig CreateConfiguration()
{
// use us-equity market hours for 'exchange is open' logic
var marketHoursDbEntry = MarketHoursDatabase.FromDataFolder().GetEntry(QuantConnect.Market.USA, null, SecurityType.Equity);
// this is the time zone the data is in, now in our case, our unvierse doesn't have 'data'
var dataTimeZone = marketHoursDbEntry.DataTimeZone;
var exchangeTimeZone = marketHoursDbEntry.ExchangeHours.TimeZone;
var symbol = Symbol.Create("pre-market-daily-us-equity-universe", SecurityType.Equity, QuantConnect.Market.USA);
return new SubscriptionDataConfig(typeof(Tick), symbol, Resolution.Daily, dataTimeZone, exchangeTimeZone, false, false, true);
}
/// <summary>
/// This funtion is used to determine at what times to fire the selection function
/// </summary>
/// <param name="startTimeUtc">The start of the interval (first date in backtest, launch time in live)</param>
/// <param name="endTimeUtc">The end of the interval (EOD last date in backtest, <see cref="Time.EndOfTime"/> in live</param>
/// <param name="marketHoursDatabase">A market hours database instance for resolving market hours</param>
/// <returns>The date time trigger times in UTC</returns>
public override IEnumerable<DateTime> GetTriggerTimes(DateTime startTimeUtc, DateTime endTimeUtc, MarketHoursDatabase marketHoursDatabase)
{
// convert times to local
var startTimeLocal = startTimeUtc.ConvertFromUtc(TimeZones.NewYork);
var endTimeLocal = endTimeUtc.ConvertFromUtc(TimeZones.NewYork);
// get the us-equity market hours
var exchangeHours = marketHoursDatabase.GetExchangeHours(QuantConnect.Market.USA, null, SecurityType.Equity);
// loop over each tradeable date in our time frame
foreach (var tradeableDate in Time.EachTradeableDay(exchangeHours, startTimeLocal, endTimeLocal))
{
// get the market open time for this date
var marketOpen = exchangeHours.GetNextMarketOpen(tradeableDate, false);
// subtract out how much time before market open we'd like to fire
yield return marketOpen - _timeBeforeMarketOpen;
}
}
}
}using QuantConnect.Data.Market;
using QuantConnect.Indicators;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
namespace QuantConnect.Algorithm.CSharp
{
// Key data types for the data manager
public struct ENFDateSymbol
{
public DateTime Date;
public string Symbol;
}
public struct ENFSignal
{
public decimal? SignalStrength;
public decimal? Probability;
}
/// <summary>
/// First full-fledged attempt at the ENF data backtesting
/// </summary>
public static class ENFDataManager
{
private static SortedDictionary<ENFDateSymbol, ENFSignal[]> enfSignalData = new SortedDictionary<ENFDateSymbol, ENFSignal[]>(new DateSymbolComparer());
private static int lineCount = 0;
/// <summary>
/// Load the data from the URL passed to Initialize()
/// </summary>
/// <returns>The number of records</returns>
/// <param name="url">The Download URL to use to download the IKF CSV data</param>
public static int LoadData(string url)
{
if (string.IsNullOrEmpty(url)) throw new ArgumentNullException("url");
// Clear any previous data and reset counters
Initialize(url);
// Load the raw data into a buffer
//var buffer = DownloadData();
// Parse the buffer into our data structure
//ParseData(buffer);
//return enfSignalData.Count;
return 50;
}
public static IEnumerable<string> SymbolList(DateTime date)
{
List<string> symbols = new List<string>() { "WINS", "CRBP", "EBR", "CC", "TWNKW", "EVI", "CYBE", "AMD", "AKS", "WLDN",
"CWEI", "PQ", "GGB", "EXEL", "MTL", "FNSR", "WB", "NVDA", "X", "HZN",
"SXCP", "ARCW", "WLB", "IDN", "HL", "NAV", "ORN", "HIQ", "OCLR", "QUAD",
"AMBR", "CDZI", "NAK", "BOOM", "LEU", "YRD", "IESC", "HDSN", "NC", "SKY",
"DLTH", "GV", "VEDL", "KEM", "RMR", "TWI", "MIME", "CARB", "SRT", "CASH"
};
Random rnd = new Random((int) DateTime.Now.Ticks & 0x0000FFFF);
symbols = symbols.OrderBy(x => rnd.Next()).Take(20).ToList();
return symbols;
}
private static void Initialize(string url)
{
DownloadUrl = url;
enfSignalData.Clear();
lineCount = 0;
}
public static DateTime FirstDate()
{
if (enfSignalData.Count < 1) throw new ApplicationException("No Data Loaded");
// Data should be sorted, so get the Date from the first record
DateTime firstDate = enfSignalData.First().Key.Date;
return firstDate;
}
public static DateTime LastDate()
{
if (enfSignalData.Count < 1) throw new ApplicationException("No Data Loaded");
// Data should be sorted, so get the Date from the last record
DateTime lastDate = enfSignalData.Last().Key.Date;
return lastDate;
}
private static string DownloadData()
{
string buffer = string.Empty;
using (var client = new WebClient())
{
buffer = client.DownloadString(DownloadUrl);
}
return buffer;
}
private static void ParseData(string buffer)
{
if (string.IsNullOrEmpty(buffer)) throw new ArgumentException("buffer");
string[] lines = buffer.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
if (lines.Count() < 1) throw new ApplicationException("No downloaded ENF data to parse.");
foreach (var line in lines)
{
lineCount++;
ParseLine(line);
}
}
private static void ParseLine(string line)
{
if (string.IsNullOrEmpty(line)) throw new ArgumentException("line");
string[] fields = line.Split(',');
if (fields.Count() != 14) throw new ApplicationException("Downloaded data (field count) line " + lineCount + " is invalid");
bool result;
DateTime date;
result = DateTime.TryParse(fields[0], out date);
if (!result) throw new ApplicationException("Downloaded data (field 0) line " + lineCount + " is invalid");
string symbol = fields[1];
int offset = 1;
for (int period = 1; period <= 6; period++)
{
string value1 = fields[period + offset];
string value2 = fields[period + offset + 1];
if (!(string.IsNullOrEmpty(value1) && string.IsNullOrEmpty(value2)))
{
decimal signalStrength;
result = decimal.TryParse(fields[period + offset], out signalStrength);
if (!result) throw new ApplicationException("Downloaded data (field " + (period + offset) + ") line " + lineCount + " is invalid");
decimal probability;
result = decimal.TryParse(fields[period + offset + 1], out probability);
if (!result) throw new ApplicationException("Downloaded data (field " + (period + offset + 1) + ") line " + lineCount + " is invalid");
AddData(date, symbol, period, signalStrength, probability);
}
offset += 1;
}
}
private static void AddData(DateTime dt, string symbol, int period, decimal signalStrength, decimal probability)
{
ENFDateSymbol ds = new ENFDateSymbol() { Date = dt, Symbol = symbol };
ENFSignal[] signals = null;
bool found = enfSignalData.TryGetValue(ds, out signals);
if (!found)
{
signals = new ENFSignal[6];
signals[period - 1] = new ENFSignal() { SignalStrength = signalStrength, Probability = probability };
enfSignalData.Add(ds, signals);
}
else
{
signals[period - 1] = new ENFSignal() { SignalStrength = signalStrength, Probability = probability };
}
}
public static string DownloadUrl { get; private set; }
}
public class DateSymbolComparer : IComparer<ENFDateSymbol>
{
public int Compare(ENFDateSymbol x, ENFDateSymbol y)
{
return ConcatValues(x).CompareTo(ConcatValues(y));
}
public string ConcatValues(ENFDateSymbol z)
{
return z.Date.ToString("yyyy-MM-dd") + "-" + z.Symbol;
}
}
}