/*
* 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.Collections.Generic;
using System.Linq;
using QuantConnect.Brokerages;
using QuantConnect.Data;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Interfaces;
using QuantConnect.Securities;
namespace QuantConnect.Lean.Engine.DataFeeds
{
///
/// Helper class to keep track of required internal currency .
/// This class is used by the
///
public class CurrencySubscriptionDataConfigManager
{
private readonly HashSet _toBeAddedCurrencySubscriptionDataConfigs;
private readonly HashSet _addedCurrencySubscriptionDataConfigs;
private bool _ensureCurrencyDataFeeds;
private bool _pendingSubscriptionDataConfigs;
private readonly CashBook _cashBook;
private readonly Resolution _defaultResolution;
private readonly SecurityManager _securityManager;
private readonly SubscriptionManager _subscriptionManager;
private readonly ISecurityService _securityService;
///
/// Creates a new instance
///
/// The cash book instance
/// The SecurityManager, required by the cash book for creating new securities
/// The SubscriptionManager, required by the cash book for creating new subscription data configs
/// The SecurityService, required by the cash book for creating new securities
/// The default resolution to use for the internal subscriptions
public CurrencySubscriptionDataConfigManager(CashBook cashBook,
SecurityManager securityManager,
SubscriptionManager subscriptionManager,
ISecurityService securityService,
Resolution defaultResolution)
{
cashBook.Updated += (sender, args) =>
{
if (args.UpdateType == CashBookUpdateType.Added)
{
_ensureCurrencyDataFeeds = true;
}
};
_defaultResolution = defaultResolution;
_pendingSubscriptionDataConfigs = false;
_securityManager = securityManager;
_subscriptionManager = subscriptionManager;
_securityService = securityService;
_cashBook = cashBook;
_addedCurrencySubscriptionDataConfigs = new HashSet();
_toBeAddedCurrencySubscriptionDataConfigs = new HashSet();
}
///
/// Will verify if there are any to be removed
/// for a given added .
///
/// The symbol that was added to the data feed system
/// The SubscriptionDataConfig to be removed, null if none
public SubscriptionDataConfig GetSubscriptionDataConfigToRemove(Symbol addedSymbol)
{
if (addedSymbol.SecurityType == SecurityType.Crypto
|| addedSymbol.SecurityType == SecurityType.CryptoFuture
|| addedSymbol.SecurityType == SecurityType.Forex
|| addedSymbol.SecurityType == SecurityType.Cfd)
{
var currencyDataFeed = _addedCurrencySubscriptionDataConfigs
.FirstOrDefault(x => x.Symbol == addedSymbol);
if (currencyDataFeed != null)
{
return currencyDataFeed;
}
}
return null;
}
///
/// Will update pending currency
///
/// True when there are pending currency subscriptions
public bool UpdatePendingSubscriptionDataConfigs(IBrokerageModel brokerageModel)
{
if (_ensureCurrencyDataFeeds)
{
// this allows us to handle the case where SetCash is called when no security has been really added
EnsureCurrencySubscriptionDataConfigs(SecurityChanges.None, brokerageModel);
}
return _pendingSubscriptionDataConfigs;
}
///
/// Will return any pending internal currency and remove them as pending.
///
/// Will return the to be added
public IEnumerable GetPendingSubscriptionDataConfigs()
{
var result = new List();
if (_pendingSubscriptionDataConfigs)
{
foreach (var subscriptionDataConfig in _toBeAddedCurrencySubscriptionDataConfigs)
{
_addedCurrencySubscriptionDataConfigs.Add(subscriptionDataConfig);
result.Add(subscriptionDataConfig);
}
_toBeAddedCurrencySubscriptionDataConfigs.Clear();
_pendingSubscriptionDataConfigs = false;
}
return result;
}
///
/// Checks the current and adds new necessary currency pair feeds to provide real time conversion data
///
public void EnsureCurrencySubscriptionDataConfigs(SecurityChanges securityChanges, IBrokerageModel brokerageModel)
{
_ensureCurrencyDataFeeds = false;
// remove any 'to be added' if the security has already been added
_toBeAddedCurrencySubscriptionDataConfigs.RemoveWhere(
config => securityChanges.AddedSecurities.Any(x => x.Symbol == config.Symbol));
var newConfigs = _cashBook.EnsureCurrencyDataFeeds(
_securityManager,
_subscriptionManager,
brokerageModel.DefaultMarkets,
securityChanges,
_securityService,
_defaultResolution);
foreach (var config in newConfigs)
{
_toBeAddedCurrencySubscriptionDataConfigs.Add(config);
}
_pendingSubscriptionDataConfigs = _toBeAddedCurrencySubscriptionDataConfigs.Any();
}
}
}