/*
* 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.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using QuantConnect.Data.UniverseSelection;
namespace QuantConnect.Algorithm.CSharp
{
///
/// Algorithm used to generate daily data on disk for the different .
/// How to use me? search for 'CHANGE ME'
/// 1- change the universe name
/// 2- change the desired start and end date to generate
/// 3- define the universe selection to use
/// Data will be generated in:
/// 'Globals.DataFolder\SecurityType\Market\universes\Resolution\{UniverseName}\{dates:yyyyMMdd}.csv'
///
/// The data produced by this algorithm is the one used by the
///
/// In the cloud, users can implement their own
/// (not using ) that can fetch the files
/// generated from this algorithm
public class ConstituentsUniverseDataGeneratorAlgorithm : QCAlgorithm
{
private readonly HashSet _currentSelection = new HashSet();
private DateTime _currentDateTime = DateTime.MinValue;
private readonly string _rootDataPath = Globals.DataFolder;
private string _dataPath;
private bool _skippedFirst;
// Configuration properties: Only these are supported for now (Don't change me)
private readonly SecurityType _securityType = SecurityType.Equity;
private readonly string _market = Market.USA;
private readonly Resolution _resolution = Resolution.Daily;
// CHANGE ME
private readonly string _universeName = "qctest";
public override void Initialize()
{
// CHANGE ME
SetStartDate(2013, 10, 07); // Set Start Date
SetEndDate(2013, 10, 11); // Set End Date
SetCash(100000); // Set Strategy Cash
UniverseSettings.Resolution = Resolution.Daily;
_dataPath = Path.Combine(_rootDataPath,
_securityType.SecurityTypeToLower(),
_market,
"universes",
_resolution.ResolutionToLower(),
_universeName);
Directory.CreateDirectory(_dataPath);
// CHANGE ME
int step = 0;
AddUniverse(coarse =>
{
step++;
switch (step)
{
case 1:
case 2:
return new[]
{
QuantConnect.Symbol.Create("QQQ", SecurityType.Equity, Market.USA),
QuantConnect.Symbol.Create("AAPL", SecurityType.Equity, Market.USA)
};
case 3:
return Enumerable.Empty();
case 4:
case 5:
return new[]
{
QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA),
QuantConnect.Symbol.Create("FB", SecurityType.Equity, Market.USA)
};
default:
throw new RegressionTestException("Unexpected step count");
}
});
Schedule.On(DateRules.EveryDay(), TimeRules.At(23, 0), SaveConstituentsUniverseDataToDisk);
}
private void SaveConstituentsUniverseDataToDisk()
{
if (_skippedFirst && Time > _currentDateTime)
{
if (Time.DayOfWeek == DayOfWeek.Sunday
|| Time.DayOfWeek == DayOfWeek.Monday)
{
// we generate files from Tue to Saturday using current selected securities
return;
}
// files are for Mon to Friday
_currentDateTime = Time.Date.AddDays(-1);
var path = Path.Combine(_dataPath, $"{_currentDateTime:yyyyMMdd}.csv");
File.Delete(path);
if (_currentSelection.Count == 0)
{
using (StreamWriter constituentsUniverseFile = new StreamWriter(path, append:true))
{
constituentsUniverseFile.WriteLine(
$"{QuantConnect.Symbol.None.Value},{QuantConnect.Symbol.None.ID.ToString()}");
}
}
else
{
foreach (var symbol in _currentSelection)
{
using (StreamWriter constituentsUniverseFile = new StreamWriter(path, append: true))
{
constituentsUniverseFile.WriteLine($"{symbol.Value},{symbol.ID.ToString()}");
}
}
}
}
_skippedFirst = true;
}
public override void OnSecuritiesChanged(SecurityChanges changes)
{
foreach (var added in changes.AddedSecurities)
{
Log($"AddedSecurities {added}");
if (_currentSelection.Contains(added.Symbol))
{
throw new RegressionTestException("Added symbol already selected");
}
_currentSelection.Add(added.Symbol);
}
foreach (var removed in changes.RemovedSecurities)
{
Log($"RemovedSecurities {removed}");
if (!_currentSelection.Contains(removed.Symbol))
{
throw new RegressionTestException("Removing symbol already deselected");
}
_currentSelection.Remove(removed.Symbol);
}
}
}
}