/*
* 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.Util;
namespace QuantConnect.Securities
{
///
/// Provides access to specific properties for various symbols
///
public class SymbolPropertiesDatabase
{
private static SymbolPropertiesDatabase _dataFolderSymbolPropertiesDatabase;
private static readonly object DataFolderSymbolPropertiesDatabaseLock = new object();
private readonly IReadOnlyDictionary _entries;
private SymbolPropertiesDatabase(IReadOnlyDictionary entries)
{
_entries = entries.ToDictionary();
}
///
/// Check whether symbol properties exists for the specified market/symbol/security-type
///
/// The market the exchange resides in, i.e, 'usa', 'fxcm', ect...
/// The particular symbol being traded
/// The security type of the symbol
public bool ContainsKey(string market, string symbol, SecurityType securityType)
{
var key = new SecurityDatabaseKey(market, symbol, securityType);
return _entries.ContainsKey(key);
}
///
/// Check whether symbol properties exists for the specified market/symbol/security-type
///
/// The market the exchange resides in, i.e, 'usa', 'fxcm', ect...
/// The particular symbol being traded (Symbol class)
/// The security type of the symbol
public bool ContainsKey(string market, Symbol symbol, SecurityType securityType)
{
return ContainsKey(
market,
MarketHoursDatabase.GetDatabaseSymbolKey(symbol),
securityType);
}
///
/// Gets the symbol properties for the specified market/symbol/security-type
///
/// The market the exchange resides in, i.e, 'usa', 'fxcm', ect...
/// The particular symbol being traded
/// The security type of the symbol
/// Specifies the quote currency to be used when returning a default instance of an entry is not found in the database
/// The symbol properties matching the specified market/symbol/security-type or null if not found
public SymbolProperties GetSymbolProperties(string market, string symbol, SecurityType securityType, string defaultQuoteCurrency)
{
SymbolProperties symbolProperties;
var key = new SecurityDatabaseKey(market, symbol, securityType);
if (!_entries.TryGetValue(key, out symbolProperties))
{
// now check with null symbol key
if (!_entries.TryGetValue(new SecurityDatabaseKey(market, null, securityType), out symbolProperties))
{
// no properties found, return object with default property values
return SymbolProperties.GetDefault(defaultQuoteCurrency);
}
}
return symbolProperties;
}
///
/// Gets the symbol properties for the specified market/symbol/security-type
///
/// The market the exchange resides in, i.e, 'usa', 'fxcm', ect...
/// The particular symbol being traded (Symbol class)
/// The security type of the symbol
/// Specifies the quote currency to be used when returning a default instance of an entry is not found in the database
/// The symbol properties matching the specified market/symbol/security-type or null if not found
public SymbolProperties GetSymbolProperties(string market, Symbol symbol, SecurityType securityType, string defaultQuoteCurrency)
{
return GetSymbolProperties(
market,
MarketHoursDatabase.GetDatabaseSymbolKey(symbol),
securityType,
defaultQuoteCurrency);
}
///
/// Gets the instance of the class produced by reading in the symbol properties
/// data found in /Data/symbol-properties/
///
/// A class that represents the data in the symbol-properties folder
public static SymbolPropertiesDatabase FromDataFolder()
{
lock (DataFolderSymbolPropertiesDatabaseLock)
{
if (_dataFolderSymbolPropertiesDatabase == null)
{
var directory = Path.Combine(Globals.DataFolder, "symbol-properties");
_dataFolderSymbolPropertiesDatabase = FromCsvFile(Path.Combine(directory, "symbol-properties-database.csv"));
}
}
return _dataFolderSymbolPropertiesDatabase;
}
///
/// Creates a new instance of the class by reading the specified csv file
///
/// The csv file to be read
/// A new instance of the class representing the data in the specified file
private static SymbolPropertiesDatabase FromCsvFile(string file)
{
var entries = new Dictionary();
if (!File.Exists(file))
{
throw new FileNotFoundException("Unable to locate symbol properties file: " + file);
}
// skip the first header line, also skip #'s as these are comment lines
foreach (var line in File.ReadLines(file).Where(x => !x.StartsWith("#") && !string.IsNullOrWhiteSpace(x)).Skip(1))
{
SecurityDatabaseKey key;
var entry = FromCsvLine(line, out key);
if (entries.ContainsKey(key))
{
throw new Exception("Encountered duplicate key while processing file: " + file + ". Key: " + key);
}
entries[key] = entry;
}
return new SymbolPropertiesDatabase(entries);
}
///
/// Creates a new instance of from the specified csv line
///
/// The csv line to be parsed
/// The key used to uniquely identify this security
/// A new for the specified csv line
private static SymbolProperties FromCsvLine(string line, out SecurityDatabaseKey key)
{
var csv = line.Split(',');
key = new SecurityDatabaseKey(
market: csv[0],
symbol: csv[1],
securityType: (SecurityType)Enum.Parse(typeof(SecurityType), csv[2], true));
return new SymbolProperties(
description: csv[3],
quoteCurrency: csv[4],
contractMultiplier: csv[5].ToDecimal(),
minimumPriceVariation: csv[6].ToDecimal(),
lotSize: csv[7].ToDecimal());
}
}
}